littlebigman Posted April 16, 2023 Posted April 16, 2023 (edited) Hello, As a quick way to get started, is there a "hello world" that shows how to… 1. open and parse an XML file 2. Search one/all elements/attributes that match a given string 3. Edit/add/remove an element 4. Save the tree into a new file ? Thank you. --- Edit: What am I doing wrong? I'm looping through all <trkpt> nodes, but either i'm using XPath incorrectly, or _XML_SelectSingleNode() doesn't like it: Source XML: <?xml version="1.0" encoding="UTF-8"?> <gpx> <metadata> <name>Some name</name> </metadata> <trk> <name>Track 1</name> <trkseg> <trkpt lat="48.81782" lon="2.24906"> <ele>123</ele> <time>Dummy time</time> </trkpt> <trkpt lat="48.81784" lon="2.24906"> <ele>456</ele> </trkpt> </trkseg> </trk> <trk> <name>Track 2</name> <trkseg> <trkpt lat="48.81782" lon="2.24906"> <ele>321</ele> </trkpt> <trkpt lat="48.81784" lon="2.24906"> <ele>654</ele> </trkpt> </trkseg> </trk> </gpx> AutoIt code: $node = '//trkpt' ;_XML_SelectNodes: Returns $oNodes_coll - Nodes collection, and set @extended = $oNodes_coll.length $oNodesColl = _XML_SelectNodes($xml, $node) For $x = 1 To $oNodesColl.length ;No way to grab nodes directly from $oNodesColl instead of calling _XML_SelectSingleNode? $query = $node & '[' & $x & ']' ConsoleWrite(StringFormat("Index : " & $x & @CRLF & "Query: %s" & @CRLF,$query)) $oNode_Selected_SingleOne = _XML_SelectSingleNode($xml, $query) If not @error Then ConsoleWrite('Lat is ' & _XML_GetNodeAttributeValue($oNode_Selected_SingleOne, 'lat') & @CRLF) Else ConsoleWrite('Error:' & @error & @CRLF & 'EXT:' & @extended & @CRLF & XML_My_ErrorParser(@error, @extended)) EndIf Next $aNodesColl = _XML_Array_GetNodesProperties($oNodesColl) _ArrayDisplay($aNodesColl, 'XPath=' & $oNodesColl.expr) Console: ;~ Index : 1 ;~ Query: //trkpt[1] ;~ Lat is 48.81782 ;~ Index : 2 ;~ Query: //trkpt[2] ;~ Lat is 48.81784 ;~ Index : 3 ;~ Query: //trkpt[3] ;~ Error:18 ;~ EXT:0 ;~ @error description: ;~ $XML_ERR_NONODESMATCH=18 ;~ No nodes match the XPath expression ;~ @extended description: ;~ $XML_EXT_DEFAULT=0 ;~ Default - Do not return any additional information ;~ Index : 4 ;~ Query: //trkpt[4] ;~ Error:18 ;~ EXT:0 ;~ @error description: ;~ $XML_ERR_NONODESMATCH=18 ;~ No nodes match the XPath expression ;~ @extended description: ;~ $XML_EXT_DEFAULT=0 ;~ Default - Do not return any additional information ArrayDisplay: -- Edit: It looks safer to first convert the collection to an array, and work with the latter: $node = '//trkpt/*' ;Selects all the child element nodes of the bookstore element $oNodesColl = _XML_SelectNodes($xml, $node) $aNodesColl = _XML_Array_GetNodesProperties($oNodesColl) Local Enum $nodeName, $nodeTypeString,$nodeValue,$nodeText,$nodeDataType,$nodeXml,$nodeAttributes _ArrayDisplay($aNodesColl, 'XPath=' & $oNodesColl.expr) For $x = 1 to UBound($aNodesColl, $UBOUND_ROWS)-1 ConsoleWrite(StringFormat("%s=%s" & @CRLF,$aNodesColl[$x][$nodeName],$aNodesColl[$x][$nodeText])) Next Edited June 1, 2023 by littlebigman
littlebigman Posted June 1, 2023 Posted June 1, 2023 (edited) (I can't figure out how to scroll down below the code above, so will reply instead.) Using that code isn't the right way to loop through each node, since it mixes everything in the array. However, the following fails. For some reason, the first two nodes (out of four) pass muster, but it crashes on the third and fourth. Is that because the last two have a different parent (trk>trkseg)? But then, isn't "//trkpt" supposed to grab all those nodes, regardless of where they live in the tree? $node = '//trkpt' $number_nodes = _XML_GetNodesCount($xml,$node) For $x = 1 To $number_nodes $current = StringFormat("%s[%s]",$node,$x) ConsoleWrite($current & @CRLF) $oNode = _XML_SelectSingleNode($xml, $current) If not @error Then ;.text = grabs everything ;$sStrippedValue = StringStripWS($oNode.text,$STR_STRIPLEADING + $STR_STRIPTRAILING) $lat = _XML_GetNodeAttributeValue($oNode, 'lat') ConsoleWrite(StringFormat("Lat is %s" & @CRLF,$lat)) Else ConsoleWrite('Error:' & @error & @CRLF & 'EXT:' & @extended & @CRLF & XML_My_ErrorParser(@error, @extended)) EndIf Next Here's the output: //trkpt[1] Lat is 48.81782 //trkpt[2] Lat is 48.81784 //trkpt[3] Error:18 EXT:0 @error description: $XML_ERR_NONODESMATCH=18 No nodes match the XPath expression @extended description: $XML_EXT_DEFAULT=0 Default - Do not return any additional information //trkpt[4] Error:18 EXT:0 @error description: $XML_ERR_NONODESMATCH=18 No nodes match the XPath expression @extended description: $XML_EXT_DEFAULT=0 Default - Do not return any additional information xidel works as expected: c:\> xidel.exe test.track.gpx -se "//trkpt" --output-node-format xml <trkpt lat="48.81782" lon="2.24906"> <ele>123</ele> <time>Dummy time</time> </trkpt> <trkpt lat="48.81784" lon="2.24906"> <ele>456</ele> </trkpt> <trkpt lat="48.81782" lon="2.24906"> <ele>321</ele> </trkpt> <trkpt lat="48.81784" lon="2.24906"> <ele>654</ele> </trkpt> --- Edit: Looks better… $node = '//trkpt' For $current in _XML_SelectNodes($xml, $node) $oNode = _XML_SelectSingleNode($current,".") ;IMPORTANT! ConsoleWrite(StringStripWS($oNode.text,$STR_STRIPLEADING + $STR_STRIPTRAILING) & @CRLF) $lat = _XML_GetNodeAttributeValue($current, 'lat') ConsoleWrite(StringFormat("Lat is %s" & @CRLF,$lat)) ConsoleWrite("=============" & @CRLF) Next Edited June 1, 2023 by littlebigman
littlebigman Posted September 22, 2023 Posted September 22, 2023 (edited) What's the right way to add a new node to a tree? I need to add a "name" node under /kml/Document: $oXmlDocIn = _XML_CreateDOMDocument() If @error Then Exit ConsoleWrite('Error:' & @error & @CRLF & 'EXT:' & @extended & @CRLF & XML_My_ErrorParser(@error, @extended)) $xml = _XML_Load($oXmlDocIn, $XML_FILE) If @error Then Exit ConsoleWrite('Error:' & @error & @CRLF & 'EXT:' & @extended & @CRLF & XML_My_ErrorParser(@error, @extended)) Switch $szExt Case ".kml" ;MsgBox($MB_OK,"Case",".kml") Local $oNode = _XML_SelectSingleNode($xml, "/kml/Document/name") If @error Then MsgBox($MB_OK,"/kml/name","Not found") ;BAD Local $iResult = _XML_InsertChildNode($xml, "/kml/Document", "name", 0,$szFName) Local $iResult = _XML_InsertChildNode($xml, "/kml/Document", "name", 0,$szFName) ;BAD Local $iResult = _XML_InsertChildNode($xml, "/kml/Document", "name",,$szFName) If @error Then MsgBox($MB_ICONERROR, 'Failed creating node:', XML_My_ErrorParser(@error)) ;~ $XML_ERR_EMPTYCOLLECTION=21 ;~ Collections of objects was empty Else ConsoleWrite(_XML_TIDY($oXMLDocIn) & @CRLF) EndIf Else MsgBox($MB_OK,"/kml/name","Found") ;Find out to edit existing node's value EndIf Case Else MsgBox($MB_OK,"Case","Other") EndSwitch Thank you. -- Edit: Could it be due to namespaces? -- Edit: Yes, indeed. I found no better way than using a regex to remove namespaces from the input file. ;kludge Local $sOutput = StringRegExpReplace(FileRead($XML_FILE), "(xmlns:?[^=]*=[""][^""]*[""])", "") Local $oXmlDocIn = _XML_CreateDOMDocument(Default) If @error Then Exit ConsoleWrite('Error:' & @error & @CRLF & 'EXT:' & @extended & @CRLF & XML_My_ErrorParser(@error, @extended)) ;Local $xml = _XML_LoadXml($oXMLDocIn, $sFileRead) ;from string _XML_LoadXml($oXmlDocIn, $sOutput) If @error Then Exit ConsoleWrite('Error:' & @error & @CRLF & 'EXT:' & @extended & @CRLF & XML_My_ErrorParser(@error, @extended)) ConsoleWrite(_XML_TIDY($oXmlDocIn) & @CRLF) Edited September 23, 2023 by littlebigman
littlebigman Posted October 5, 2023 Posted October 5, 2023 (edited) Does someone know how to inject a whole XML sequence in one go? Local Const $LS = "<Style><color>00FF00</color><width>3</width></Style>" ;~ After insert/append: ;~ <parent> ;~ <Style> ;~ <color>00FF00</color> ;~ <width>3</width> ;~ </Style> ;~ </parent> ;BAD _XML_InsertChildNode($oXmlDocInTMP,"//Placemark",$LS,0,"blah") ;Try child DOM object ;NOTHING Local $oXmlDocInTMP_LS = _XML_CreateDOMDocument(Default) _XML_LoadXml($oXmlDocInTMP_LS, $LS) _XML_InsertChildNode($oXmlDocInTMP,"//Placemark",_XML_TIDY($oXmlDocInTMP_LS, "UTF-8"),0,"blah") ConsoleWrite(_XML_TIDY($oXmlDocInTMP, "UTF-8")) ;create then insert? --- Edit: Getting closer… but still NOK. Since the UDF provides no _XML_CreateNode() or _XML_CreateChild(), I used _XML_CreateChildWAttr() with a useless attribute. It works, but, half-surprisingly, since the data is part of the node's text/value/string, HTML brackets are turned into text instead of actual XML : Local Const $LS = "<Style><LineStyle><color>FF0000FF</color><width>6</width></LineStyle></Style>" Local $aAttributeList[1][2] = [['First', '1']] ; Just to keep _XML_CreateChildWAttr() happy _XML_CreateChildWAttr($oXmlDocInTMP, "//Placemark", 'Style', $aAttributeList, "<color>00FF00</color><width>3</width>") ConsoleWrite(_XML_TIDY($oXmlDocInTMP) & @CRLF) OUTPUT: Quote <?xml version="1.0" encoding="UTF-8" standalone="no"?> <kml> ... <Style First="1"><color>00FF00</color><width>3</width></Style> </Placemark> <Placemark> ... </Document> </kml> --- Edit: Yeah! Apparently, you need to use the COM object directly to use its append() method: Local $oXmlDocInTMP_LS = _XML_CreateDOMDocument(Default) _XML_LoadXml($oXmlDocInTMP_LS, "<Style><LineStyle><color>FF0000FF</color><width>6</width></LineStyle></Style>") Local $oParent = _XML_SelectSingleNode($oXmlDocInTMP, "//Placemark[1]") $oParent.appendChild($oXmlDocInTMP_LS.selectSingleNode("//Style")) ConsoleWrite(_XML_TIDY($oXmlDocInTMP) & @CRLF) _XML_SaveToFile($oXmlDocInTMP, "test.outout.kml") --- Edit: For some reason, in the loop, appendChild() only adds the child to the last node ;new, sub-tree to add to main tree Local $oXmlDocInTMP_LS = _XML_CreateDOMDocument(Default) _XML_LoadXml($oXmlDocInTMP_LS, "<Style><LineStyle><color>FF0000FF</color><width>6</width></LineStyle></Style>") ;pointer to root node in tree Local $oStyle = $oXmlDocInTMP_LS.selectSingleNode("//Style") ;oXmlDocInTMP = main tree Local $oNodesColl = _XML_SelectNodes($oXmlDocInTMP, "//Placemark") For $oNodeEnum In $oNodesColl ;Why is child only added to last node? $oNodeEnum.appendChild($oStyle) Next ConsoleWrite(_XML_TIDY($oXmlDocInTMP) & @CRLF) Could it be the for/in/next loop doesn't work with elements from an XML tree? Edited October 5, 2023 by littlebigman
mLipok Posted 17 hours ago Author Posted 17 hours ago A new era is coming: https://github.com/mlipok/XML.au3 Integrated with AI ChatGPT WildByDesign 1 Signature beginning:* Please remember: "AutoIt"..... * Wondering who uses AutoIt and what it can be used for ? * Forum Rules ** ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Code * for other useful stuff click the following button: Spoiler Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API * ErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 * My contribution to others projects or UDF based on others projects: * _sql.au3 UDF * POP3.au3 UDF * RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF * SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane * Useful links: * Forum Rules * Forum etiquette * Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * Wiki: * Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX IE Related: * How to use IE.au3 UDF with AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskScheduler * IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related: * How to get reference to PDF object embeded in IE * IE on Windows 11 * I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions * EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *I also encourage you to check awesome @trancexx code: * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuff * OnHungApp handler * Avoid "AutoIt Error" message box in unknown errors * HTML editor * winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/ "Homo sum; humani nil a me alienum puto" - Publius Terentius Afer"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming" , be and \\//_. Anticipating Errors : "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty." Signature last update: 2023-04-24
mLipok Posted 16 hours ago Author Posted 16 hours ago (edited) https://github.com/mlipok/XML.au3/releases#release-XML_1.1.1.13 Edited 16 hours ago by mLipok Signature beginning:* Please remember: "AutoIt"..... * Wondering who uses AutoIt and what it can be used for ? * Forum Rules ** ADO.au3 UDF * POP3.au3 UDF * XML.au3 UDF * IE on Windows 11 * How to ask ChatGPT for AutoIt Code * for other useful stuff click the following button: Spoiler Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind. My contribution (my own projects): * Debenu Quick PDF Library - UDF * Debenu PDF Viewer SDK - UDF * Acrobat Reader - ActiveX Viewer * UDF for PDFCreator v1.x.x * XZip - UDF * AppCompatFlags UDF * CrowdinAPI UDF * _WinMergeCompare2Files() * _JavaExceptionAdd() * _IsBeta() * Writing DPI Awareness App - workaround * _AutoIt_RequiredVersion() * Chilkatsoft.au3 UDF * TeamViewer.au3 UDF * JavaManagement UDF * VIES over SOAP * WinSCP UDF * GHAPI UDF - modest begining - comunication with GitHub REST API * ErrorLog.au3 UDF - A logging Library * Include Dependency Tree (Tool for analyzing script relations) * Show_Macro_Values.au3 * My contribution to others projects or UDF based on others projects: * _sql.au3 UDF * POP3.au3 UDF * RTF Printer - UDF * XML.au3 UDF * ADO.au3 UDF * SMTP Mailer UDF * Dual Monitor resolution detection * * 2GUI on Dual Monitor System * _SciLexer.au3 UDF * SciTE - Lexer for console pane * Useful links: * Forum Rules * Forum etiquette * Forum Information and FAQs * How to post code on the forum * AutoIt Online Documentation * AutoIt Online Beta Documentation * SciTE4AutoIt3 getting started * Convert text blocks to AutoIt code * Games made in Autoit * Programming related sites * Polish AutoIt Tutorial * DllCall Code Generator * Wiki: * Expand your knowledge - AutoIt Wiki * Collection of User Defined Functions * How to use HelpFile * Good coding practices in AutoIt * OpenOffice/LibreOffice/XLS Related: WriterDemo.au3 * XLS/MDB from scratch with ADOX IE Related: * How to use IE.au3 UDF with AutoIt v3.3.14.x * Why isn't Autoit able to click a Javascript Dialog? * Clicking javascript button with no ID * IE document >> save as MHT file * IETab Switcher (by LarsJ ) * HTML Entities * _IEquerySelectorAll() (by uncommon) * IE in TaskScheduler * IE Embedded Control Versioning (use IE9+ and HTML5 in a GUI) * PDF Related: * How to get reference to PDF object embeded in IE * IE on Windows 11 * I encourage you to read: * Global Vars * Best Coding Practices * Please explain code used in Help file for several File functions * OOP-like approach in AutoIt * UDF-Spec Questions * EXAMPLE: How To Catch ConsoleWrite() output to a file or to CMD *I also encourage you to check awesome @trancexx code: * Create COM objects from modules without any demand on user to register anything. * Another COM object registering stuff * OnHungApp handler * Avoid "AutoIt Error" message box in unknown errors * HTML editor * winhttp.au3 related : * https://www.autoitscript.com/forum/topic/206771-winhttpau3-download-problem-youre-speaking-plain-http-to-an-ssl-enabled-server-port/ "Homo sum; humani nil a me alienum puto" - Publius Terentius Afer"Program are meant to be read by humans and only incidentally for computers and execute" - Donald Knuth, "The Art of Computer Programming" , be and \\//_. Anticipating Errors : "Any program that accepts data from a user must include code to validate that data before sending it to the data store. You cannot rely on the data store, ...., or even your programming language to notify you of problems. You must check every byte entered by your users, making sure that data is the correct type for its field and that required fields are not empty." Signature last update: 2023-04-24
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now