Format XML - Remove node based on element

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
buffedbygod
Posts: 3
Joined: 13 Feb 2019, 08:39

Format XML - Remove node based on element

13 Feb 2019, 08:48

Hi.

So I've used AHK for many things and it's great, but I am a noob when it comes to XML. What is the easiest way to do this?

Code: Select all

<report>
	<subject>
 	 	<id type="integer">1111111111</id>
	 	<numer type="integer">123</number>
	</subject>
	<subject>
 		<id type="integer">222222222</id>
		<numer type="integer">789</number>
	</subject>
	<subject>
 		<id type="integer">1111111111</id>
 		<numer type="integer">456</number>
	</subject>
	<subject>
 		<id type="integer">222222222</id>
		<numer type="integer">159</number>
	</subject>
</report>
I want to remove all nodes that are containing the id "222222222". So the result would be:

Code: Select all

<report>
	<subject>
 	 	<id type="integer">1111111111</id>
	 	<numer type="integer">123</number>
	</subject>
	<subject>
 		<id type="integer">1111111111</id>
 		<numer type="integer">456</number>
	</subject>
</report>
Thanks.
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Format XML - Remove node based on element

13 Feb 2019, 09:42

What is your XML, is it a file or text in your script?
buffedbygod
Posts: 3
Joined: 13 Feb 2019, 08:39

Re: Format XML - Remove node based on element

13 Feb 2019, 10:38

teadrinker wrote:
13 Feb 2019, 09:42
What is your XML, is it a file or text in your script?
It is a document. So far I've gotten so far. But now I'm stuck again.

Code: Select all

FileRead, xmldata, C:\file.xml
doc := ComObjCreate("MSXML2.DOMDocument.6.0")
doc.async := false
doc.loadXML(xmldata)

DocNode := doc.selectSingleNode("//subject/id")

shittyVariable := DocNode.text
msgbox %shittyVariable%
return
So I can find what I want, but once I've found the "ID", how can I delete it's parent node?
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Format XML - Remove node based on element

13 Feb 2019, 11:10

Like this:

Code: Select all

xmlPath := "C:\file.xml"
xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
xmlDoc.async := false
xmlDoc.load(xmlPath)

for item in xmlDoc.getElementsByTagName("id") {
   if (item.text == "222222222") {
      parent := item.parentNode
      parent.parentNode.removeChild(parent)
   }
}
xmlDoc.Save(xmlPath)
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Format XML - Remove node based on element

13 Feb 2019, 12:20

You could also use another approach:

Code: Select all

text =
(
<report>
   <subject>
        <id type="integer">1111111111</id>
       <number type="integer">123</number>
   </subject>
   <subject>
       <id type="integer">222222222</id>
      <number type="integer">789</number>
   </subject>
   <subject>
       <id type="integer">1111111111</id>
       <number type="integer">456</number>
   </subject>
   <subject>
       <id type="integer">222222222</id>
      <number type="integer">159</number>
   </subject>
</report>
)
textToRemove := "222222222"

pattern := RegExReplace(textToRemove, "\\|\.|\*|\?|\+|\[|\{|\||\(|\)|\^|\$", "\$0")
MsgBox, % RegExReplace(text, "s)\s*<([^>]+)>((?!</(?1)>).)+<id(\s|>)((?!</id>).)*" . pattern . "</id>.*?</\1>")
buffedbygod
Posts: 3
Joined: 13 Feb 2019, 08:39

Re: Format XML - Remove node based on element

15 Feb 2019, 04:53

teadrinker wrote:
13 Feb 2019, 11:10
Like this:

Code: Select all

xmlPath := "C:\file.xml"
xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
xmlDoc.async := false
xmlDoc.load(xmlPath)

for item in xmlDoc.getElementsByTagName("id") {
   if (item.text == "222222222") {
      parent := item.parentNode
      parent.parentNode.removeChild(parent)
   }
}
xmlDoc.Save(xmlPath)
This is great. Thank you you've been helpful.
I find it hard to find somewhere to read up on this stuff. I can't find a good manual/guide.

I want to loop through all <subject> tags, get the text value of some specific child-nodes and save them in a file.

Code: Select all

for item in xmlDoc.getElementsByTagName("subject") {
	string := item.text ;works
	stringTwo := item.getAttribute("id").text ;doesn't work
}
}
How can I do this? I feel kind of stupid but I can't find the answer so I have to ask.
just me
Posts: 9456
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Format XML - Remove node based on element

15 Feb 2019, 05:39

<id> is a childnode and not an attribute (in this case).

Code: Select all

; ================================================================================================================================
; XPATH syntax -> msdn.microsoft.com/en-us/library/ms256471(v=vs.110).aspx
; XML node class -> msdn.microsoft.com/en-us/library/system.xml.xmlnode(v=vs.110).aspx
; DOM reference -> msdn.microsoft.com/en-us/library/ms764730(v=vs.85).aspx
; ================================================================================================================================
#NoEnv
XML =
(Join`r`n
<report>
	<subject>
 	 	<id type="integer">1111111111</id>
	 	<number type="integer">123</number>
	</subject>
	<subject>
 		<id type="integer">222222222</id>
		<number type="integer">789</number>
	</subject>
	<subject>
 		<id type="integer">1111111111</id>
 		<number type="integer">456</number>
	</subject>
	<subject>
 		<id type="integer">222222222</id>
		<number type="integer">159</number>
	</subject>
</report>
)

xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
xmlDoc.async := False
xmlDoc.loadXML(XML)
If (xmlDoc.parseError.errorCode != 0) {
   MsgBox, % "You have error " . xmlDoc.parseError.reason
   ExitApp
}

For Item In xmlDoc.getElementsByTagName("subject") {
	string := Item.text ;works
   stringTwo := ""
   For Child In Item.childNodes
      stringTwo .= "`n" . Child.nodeName . " - " . Child.nodeType . " - " . Child.nodeValue . " - " . Child.text
	MsgBox, 0, <subject> #%A_Index%, %string%%stringTwo%
}

xmlDoc := ""
ExitApp
teadrinker
Posts: 4330
Joined: 29 Mar 2015, 09:41
Contact:

Re: Format XML - Remove node based on element

15 Feb 2019, 05:40

buffedbygod wrote: I find it hard to find somewhere to read up on this stuff. I can't find a good manual/guide.
Try reading:
DOM Concepts
Working with XML Document Parts
I want to loop through all <subject> tags, get the text value of some specific child-nodes and save them in a file.
An example:

Code: Select all

xmlPath := "C:\file.xml"
xmlDoc := ComObjCreate("MSXML2.DOMDocument.6.0")
xmlDoc.async := false
xmlDoc.load(xmlPath)

for item in xmlDoc.getElementsByTagName("subject") {
   for item in item.childNodes {
      MsgBox, % item.xml . "`n`n" item.text
   }
}

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: alawsareps, Chunjee, Joey5, Rohwedder and 336 guests