locked
Comparing XML Nodes RRS feed

  • Question

  • Thanks for taking a look!

    I want to compare the first 2 XML files and produce the 3rd containing the differences but also retaining the ancestors of the differences.  Is there a simple powershell method or will I need to read and compare each node?

    These files are small examples - the real one will have a lot more entries.

    File 1.

    <people> <person username="tester"> <title>Tester</title> <displayname>Jon Tester</displayname> </person> </people>

    File 2

    <people>
      <person username="tester">
          <title>Senior Tester</title>
    	  <displayname>Jon Tester</displayname>
      </person>
    </people>
    
    

    Result File

    <people>
      <person username="tester">
          <title>Senior Tester</title>
      </person>
    </people>
    

    Thursday, December 18, 2014 4:28 AM

Answers

  • Hi Julian,

    In addition, the script below is for your reference, which can list and loop the child nodes under "people\person", then if there is the same value found in every childnode in xml1, the script will move this childnode, finally it will save as the xml file.

    $xml=[xml]@'
    <people>
      <person username="tester">
          <title>Tester</title>
           <displayname>Jon Tester</displayname>
           <profession>engineer</profession>
           <age>987654321</age>
           <daystoretire>12345678</daystoretire>
      </person>
    </people>
    '@
    
    $xml1=[xml]@'
    <people>
      <person username="tester">
          <title>Tester</title>
    	  <displayname>Jon Tester XYZ</displayname>
           <profession>unknown</profession>
           <age>987654321</age>
           <daystoretire>12345679</daystoretire>
      </person>
    </people>
    '@
    
    
    $xml.SelectNodes("people/person/*")|select -ExpandProperty name|foreach{  #list child nodes under persoon
    $jud = $xml.SelectSingleNode("//$_")."#text"
    $jud1 = $xml1.SelectSingleNode("//$_")."#text"
    if($jud -eq $jud1){  #judge if the childnode has the same value
    $node = $xml1.SelectSingleNode("//$_")
    while ($node -ne $null) {
        $node.ParentNode.RemoveChild($node)  #remove the same childnode
        $node = $xml1.SelectSingleNode("//$_")}
    		}
    }
    
    $xml1.save("d:\1.xml")

    If there is anything else regarding this issue, please feel free to post back.

    Best Regards,

    Anna Wang


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. If you have feedback for TechNet Support, contact tnmff@microsoft.com

    • Edited by AnnaWY Monday, December 29, 2014 7:30 AM
    • Proposed as answer by AnnaWY Monday, January 5, 2015 2:09 AM
    • Marked as answer by AnnaWY Wednesday, January 7, 2015 1:38 AM
    Monday, December 29, 2014 7:29 AM

All replies

  • The XML will represent people. Each person will have a username which makes it unique from others.  Each person will have a number of attributes but never multiple of the same attribute.  So the "Difference" file should always contain

    a) only users that had attributes change

    b) the ancestors of those attribute changes.

    Thanks

    Thursday, December 18, 2014 7:59 PM
  • Hi Thanks for the reply.

    First - I needed to change $xml1 and $sml2 to $file1, $file2 or else the Powershell ISE always interpreted the files as XML.

    Then I confirmed it works OK but I'm not sure I can use such a simple method in my scenario as there will be potentially have

    a) new <person> nodes in the second file and not necessarily at the end.

    b) extra child nodes for a person (ie not all persons have the same list of attributes)

    c) different order of child nodes in  both files (I may be able to ensure they are identical)

    Any of those items will throw out the comparison.

    I think I need to process like this: 

    • find a person in both files 
    • compare each child node with it's counterpart in the other file (if it is there at all)

    Cheers

    Monday, December 22, 2014 12:56 AM
  • Hi Julian,

    In addition, the script below is for your reference, which can list and loop the child nodes under "people\person", then if there is the same value found in every childnode in xml1, the script will move this childnode, finally it will save as the xml file.

    $xml=[xml]@'
    <people>
      <person username="tester">
          <title>Tester</title>
           <displayname>Jon Tester</displayname>
           <profession>engineer</profession>
           <age>987654321</age>
           <daystoretire>12345678</daystoretire>
      </person>
    </people>
    '@
    
    $xml1=[xml]@'
    <people>
      <person username="tester">
          <title>Tester</title>
    	  <displayname>Jon Tester XYZ</displayname>
           <profession>unknown</profession>
           <age>987654321</age>
           <daystoretire>12345679</daystoretire>
      </person>
    </people>
    '@
    
    
    $xml.SelectNodes("people/person/*")|select -ExpandProperty name|foreach{  #list child nodes under persoon
    $jud = $xml.SelectSingleNode("//$_")."#text"
    $jud1 = $xml1.SelectSingleNode("//$_")."#text"
    if($jud -eq $jud1){  #judge if the childnode has the same value
    $node = $xml1.SelectSingleNode("//$_")
    while ($node -ne $null) {
        $node.ParentNode.RemoveChild($node)  #remove the same childnode
        $node = $xml1.SelectSingleNode("//$_")}
    		}
    }
    
    $xml1.save("d:\1.xml")

    If there is anything else regarding this issue, please feel free to post back.

    Best Regards,

    Anna Wang


    Please remember to mark the replies as answers if they help and unmark them if they provide no help. If you have feedback for TechNet Support, contact tnmff@microsoft.com

    • Edited by AnnaWY Monday, December 29, 2014 7:30 AM
    • Proposed as answer by AnnaWY Monday, January 5, 2015 2:09 AM
    • Marked as answer by AnnaWY Wednesday, January 7, 2015 1:38 AM
    Monday, December 29, 2014 7:29 AM
  • Thanks Anna. Your example script is exactly what I needed.
    Monday, January 12, 2015 4:02 AM