Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Remove XML element from a node

4,899 views
Skip to first unread message

paulw

unread,
Dec 18, 2008, 8:50:01 PM12/18/08
to
I have a XML file and I would like to remove an element. The element I would
like to remove "Version". I managed to figure out how to change the value
and remove the parent (NRCS). It would be easy enough to parse the file and
remove the line but I figure there has to be a proper way.

<JEDevParams>
<Login>
<AMServer></AMServer>
<NRCSServer></NRCSServer>
<User></User>
<Password></Password> // only used for autotest
</Login>
<NRCS>
<Version>2.1.1.20</Version>
<SearchLimit>300</SearchLimit>
<SkipFolderCount>yes</SkipFolderCount> // yes = don't get count for
browser folders
</NRCS>
</JEDevParams>

Here is what I thought would work:

[xml] $xml = get-content "F:\Scripts\Test\JEDevParams.xml"
$rootParams = $xml.SelectSingleNode("//JEDevParams")
#$rootParams.NRCS.Version==
$nodes = $rootParams.SelectNodes("NRCS")

for ($i=0; $i -lt $nodes.Count; $i++)
{
if ($nodes[$i].SelectSingleNode("Version").InnerText -eq "2.1.1.20")
{
$rootParams.RemoveChild($nodes[$i])
}
}
$xml.Save("F:\Test\JEDevResult.xml")

Kiron

unread,
Dec 18, 2008, 11:59:12 PM12/18/08
to
Use the parent node's RemoveChild() Method. To filter and select the node(s) use XPath notation.

Here are three ways to delete the Version child node of the first NRCS node:
$xml.Save([console]::out);'' just writes the xml to the console.

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$nrcs = $xml.SelectSingleNode('//NRCS')
$version = $nrcs.SelectSingleNode('Version')
[void]$nrcs.RemoveChild($version)
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_1.xml')

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$version = $xml.SelectSingleNode('//Version')
[void]$version.ParentNode.RemoveChild($version)
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_2.xml')

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$nrcs = $xml.SelectSingleNode('//NRCS')
[void]$nrcs.RemoveChild($nrcs.SelectSingleNode('Version'))
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_3.xml')

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
Same three ways but this time deletes the Version child node of all NRCS nodes:

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$xml.SelectNodes('//NRCS') | % {
$version = $_.SelectSingleNode('Version')
[void]$_.RemoveChild($version)
}
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_1.xml')

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$xml.SelectNodes('//Version') | % {
[void]$_.ParentNode.RemoveChild($_)
}
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_2.xml')

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$xml.SelectNodes('//NRCS') | % {
[void]$_.RemoveChild($_.SelectSingleNode('Version'))
}
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_3.xml')

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - #
Same three ways but this time deletes the Version child node of all NRCS nodes, whose #text equals "2.1.1.20":

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$xml.SelectNodes('//NRCS[./Version="2.1.1.20"]') | % {
$version = $_.SelectSingleNode('Version')
[void]$_.RemoveChild($version)
}
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_1.xml')

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$xml.SelectNodes('//Version[.="2.1.1.20"]') | % {
[void]$_.ParentNode.RemoveChild($_)
}
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_2.xml')

[xml]$xml = gc F:\Scripts\Test\JEDevParams.xml
$xml.SelectNodes('//NRCS[./Version="2.1.1.20"]') | % {
[void]$_.RemoveChild($_.SelectSingleNode('Version'))
}
$xml.Save([console]::out);''
$xml.Save('F:\Test\JEDevResult_3.xml')

--
Kiron

Keith Hill [MVP]

unread,
Dec 19, 2008, 12:21:27 AM12/19/08
to
"paulw" <pa...@discussions.microsoft.com> wrote in message
news:E9B5A208-39DB-4FF2...@microsoft.com...

You're close. Try this:

PS> [xml]$xml = @'


>> <JEDevParams>
>> <Login>
>> <AMServer></AMServer>
>> <NRCSServer></NRCSServer>
>> <User></User>
>> <Password></Password> // only used for autotest
>> </Login>
>> <NRCS>
>> <Version>2.1.1.20</Version>
>> <SearchLimit>300</SearchLimit>
>> <SkipFolderCount>yes</SkipFolderCount> // yes = don't get count for
>> browser folders
>> </NRCS>
>> </JEDevParams>

>> '@
>>

PS> $xml | fxml


<JEDevParams>
<Login>
<AMServer></AMServer>
<NRCSServer></NRCSServer>
<User></User>
<Password></Password> // only used for autotest
</Login>
<NRCS>
<Version>2.1.1.20</Version>
<SearchLimit>300</SearchLimit>
<SkipFolderCount>yes</SkipFolderCount> // yes = don't get count for
browser folders
</NRCS>
</JEDevParams>

PS> $xml.JEDevParams.NRCS.RemoveChild($xml.SelectSingleNode('//Version'))

#text
-----
2.1.1.20


PS> $xml | fxml


<JEDevParams>
<Login>
<AMServer></AMServer>
<NRCSServer></NRCSServer>
<User></User>
<Password></Password> // only used for autotest
</Login>
<NRCS>

<SearchLimit>300</SearchLimit>
<SkipFolderCount>yes</SkipFolderCount> // yes = don't get count for
browser folders
</NRCS>
</JEDevParams>

Note that fxml (format-xml) is a cmdlet provide by the PowerShell Community
Extensions.

--
Keith Hill
http://www.codeplex.com/powershellcx

paulw

unread,
Dec 19, 2008, 9:15:06 PM12/19/08
to
Thanks. It worked. I installed the PowerShell extensions. There is a lot of
great stuff in the package.

I think I found a limitation/bug in format-xml. When I was playing around
with it this afternoon, I was a bit confused because it was not formatting
the XML from my source file very well. I simplifieed the source file (eg
removed comments) and it worked fine. I went back and added some comments and
found that the function works fine when the comments are in some contexts
but not others.

For example, the format-xml will format contains lines like the following
line without a problem:
...
<NRCSServer></NRCSServer> // Comment 2
...

However, the formatting gets gummed up with the following:

<?xml version="1.0" encoding="UTF8"?>
<JEDevParams>
//Comment
//Comment
<Login>...


Keith Hill [MVP]

unread,
Dec 22, 2008, 5:58:19 PM12/22/08
to
"paulw" <pa...@discussions.microsoft.com> wrote in message
news:1F6816D8-69B4-406B...@microsoft.com...

FYI the "// Comment 2" would be considered text within XML. XML comments
are delineated like so:

<!-- comment here -->

The two "//Comment" lines above would be considered text nodes within the
root element JEDevParams. But I do see what you are saying. The presence
of text nodes is messing up the formatting. I'll take a look at that.

Thanks,
Keith

Irwin@discussions.microsoft.com Ryan Irwin

unread,
May 13, 2010, 11:33:01 PM5/13/10
to
I know I'm replying to a very old post, but I'm hoping someone can help me.
I have an xml with prepopulated nodes. I want to save one child node out of
many based on a condition, remove all of the other child nodes, and then
stick the saved child node back in. I can't see why it wouldn't be possible,
but I can't seem to wrap my head around how to get it done. Any help would
be greatly appreciated.

-Ryan Irwin

Ryan Irwin

unread,
May 14, 2010, 9:09:01 AM5/14/10
to
More specifically, here's how the xml is laid out:

<?xml version="1.0" encoding="utf-8" ?>
<Addresses version="1.0">
<Contacts>
<Contact name="ABC Company" type="business">
<Street>123 Anywhere St</Street>
<City>Someplace</City>
<State>AA</State>
<Zip>12345</Zip>
<Phone>555-123-4567</Phone>
</Contact>
<Contact name="John Doe" type="personal">
<Phone>555-333-4444</Phone>
</Contact>
</Contacts>
</Addresses>

I would like to save the contact node based on the type of personal, delete
any other node whose type does not match personal.

What I can't seem to figure out is how to drill down to the "type" level.

Michael Soza

unread,
May 14, 2010, 7:00:00 PM5/14/10
to
You can do something like this, here test.xml is your file.

$xmldata= [xml] (Get-Content .\test.xml)
$xmldata.SelectNodes("//Contact[@type!=`"personal`"]") | % {
$xmldata.SelectNodes("//Contacts").item(0).removechild($_)}
$xmldata.save((pwd).path+"\nuevo.xml")


The key in this is the string writed in xpath....you can find examples for
xpath here http://msdn.microsoft.com/en-us/library/ms256086.aspx
Good luck.

Michael Soza.

"Ryan Irwin" <Ryan...@discussions.microsoft.com> wrote in message
news:29BBFB3E-C319-484C...@microsoft.com...

Ryan Irwin

unread,
May 14, 2010, 9:46:01 PM5/14/10
to

Michael

Thank you so much, that was exactly what I needed, now to reverse engineer
it so I better understand what it's doing and how I can use it in other
applications. (Total PS newbie here).

Thanks again,
Ryan

Michael Soza

unread,
May 14, 2010, 10:19:09 PM5/14/10
to
I recommend that you read the book Mastering Powershell form Dr. Tobias
Weltner, is free, and simple to understand. In one or two hour you can
understand all the basics.
The link is http://powershell.com/Mastering-PowerShell.pdf.
Happy reading.

"Ryan Irwin" <Ryan...@discussions.microsoft.com> wrote in message

news:0FCB7114-439B-453C...@microsoft.com...

Ryan Irwin

unread,
May 16, 2010, 9:55:01 AM5/16/10
to
Wow, thanks for pointing me to that. Now I have something to read while on
vacation =). Thanks again for your help!
0 new messages