ViConst
ViConst

Reputation: 11

How to filter out nodes in XML using PowerShell?

I would really appreciate any help you may have, regarding the following problem:

XML data is stored in .xml file.

I would like to filter-out some XML nodes if they have the proper "distinguishedname" (verifying it either by name).

Below is the XML structure:

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>Selected.Microsoft.ActiveDirectory.Management.ADGroup</T>
      <T>System.Management.Automation.PSCustomObject</T>
      <T>System.Object</T>
    </TN>
    <MS>
      <S N="Samaccountname">user.name</S>
      <S N="distinguishedname">CN=Domain Users,CN=Users,DC=company,DC=com</S>
    </MS>
  <Obj RefId="1">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name1</S>
      <S N="distinguishedname">CN=app_name_1,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="2">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name1</S>
      <S N="distinguishedname">CN=app_name_2,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="3">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name2</S>
      <S N="distinguishedname">CN=CN=app_name_3,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="4">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name2</S>
      <S N="distinguishedname">CN=app_name_4,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
</Objs>

The content reads first

$filedata = gc $Env:HOMEDRIVE\users.xml

And then filtering out

$filedata = foreach ($obj in $filexml.Objs.Obj){
        $obj.MS.S | ?{ $_.N -eq "distinguishedname"} | 
        %{if( $_."#text" -match "*name_1" -or $_."#text" -match "*name_4*") 
    {$obj}}}

In my example <Obj RefId="2"> and <Obj RefId="4"> are OK and should be filtered, and <Obj RefId="0"> and <Obj RefId="1"> should be completely removed from the XML.

I would really appreciate any advice!

Upvotes: 1

Views: 3769

Answers (2)

dugas
dugas

Reputation: 12443

Assuming the following xml, and the goal is to remove all Obj RefId that do not equal 2 and 4:

<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
<Obj RefId="0">
<TN RefId="0">
  <T>Selected.Microsoft.ActiveDirectory.Management.ADGroup</T>
  <T>System.Management.Automation.PSCustomObject</T>
  <T>System.Object</T>
</TN>
<MS>
  <S N="Samaccountname">user.name</S>
  <S N="distinguishedname">CN=Domain Users,CN=Users,DC=company,DC=com</S>
</MS>
</Obj>
<Obj RefId="1">
<TNRef RefId="0" />
<MS>
  <S N="Samaccountname">user.name1</S>
  <S N="distinguishedname">CN=app_name_1,OU=publ,OU=app,DC=comp,DC=com</S>
</MS>
</Obj>
<Obj RefId="2">
<TNRef RefId="0" />
<MS>
  <S N="Samaccountname">user.name1</S>
  <S N="distinguishedname">CN=app_name_2,OU=publ,OU=app,DC=comp,DC=com</S>
</MS>
</Obj>
<Obj RefId="3">
<TNRef RefId="0" />
<MS>
  <S N="Samaccountname">user.name2</S>
  <S N="distinguishedname">CN=CN=app_name_3,OU=publ,OU=app,DC=comp,DC=com</S>
</MS>
</Obj>
<Obj RefId="4">
<TNRef RefId="0" />
<MS>
  <S N="Samaccountname">user.name2</S>
  <S N="distinguishedname">CN=app_name_4,OU=publ,OU=app,DC=comp,DC=com</S>
</MS>
</Obj>
</Objs>

Define filters:

$filters = [regex]".*(name_2|name_4).*"

Load xml:

$xml = [xml](Get-Content "$home\Documents\test.xml")

Remove unwanted elements:

$xml.Objs.Obj | ?{ ($_.MS.S | ?{$_.N -eq "distinguishedname"}).'#text' -notmatch $filters} | %{$xml.Objs.RemoveChild($_)}

Save xml:

$xml.Save("$home\Documents\test2.xml")

Upvotes: 0

Kev Hunter
Kev Hunter

Reputation: 2625

Well, for a start you are not assigning the variable $filexml as anything so you probably need

$filexml = [xml] fileData

If you're not using powershell ISE to debug your code you are missing out, setting a breakpoint on your foreach would have shown you that the $FileXml variable was null

And your xml is invalid, it should be

    <Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <Obj RefId="0">
    <TN RefId="0">
      <T>Selected.Microsoft.ActiveDirectory.Management.ADGroup</T>
      <T>System.Management.Automation.PSCustomObject</T>
      <T>System.Object</T>
    </TN>
    <MS>

      <S N="Samaccountname">user.name</S>
      <S N="distinguishedname">CN=Domain Users,CN=Users,DC=company,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="1">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name1</S>
      <S N="distinguishedname">CN=app_name_1,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="2">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name1</S>
      <S N="distinguishedname">CN=app_name_2,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="3">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name2</S>
      <S N="distinguishedname">CN=CN=app_name_3,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
  <Obj RefId="4">
    <TNRef RefId="0" />
    <MS>
      <S N="Samaccountname">user.name2</S>
      <S N="distinguishedname">CN=app_name_4,OU=publ,OU=app,DC=comp,DC=com</S>
    </MS>
  </Obj>
</Objs>

Upvotes: 3

Related Questions