Learning_something_new
Learning_something_new

Reputation: 107

PowerShell command to check the XML file

I am trying to learn accessing XML files through PowerShell.

The requirement is to check through PowerShell and see if the <street>Baker street 1</street> exist in all the three xml files.

Below are the 3 XML file and its path:

Path C:\Desktop\Path1\XML Path

1. Joe.xml

<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation='test.xsd'>
    <address>
        <street>Baker street 1</street>
        <name>Joe Tester</name>
        <age>20</age>
        <university>A - UNIVERSITY</university>
    </address>
</addresses>

2. Jack.xml

<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation='test.xsd'>
    <address>
        <name>Jack</name>
        <age>19</age>
        <university>B - UNIVERSITY</university>
    </address>
</addresses>

3. Ryan.xml

<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:noNamespaceSchemaLocation='test.xsd'>
    <address>
        <name>Ryan</name>
        <age>23</age>
        <university>C - UNIVERSITY</university>
    </address>
</addresses>

If the <street>Baker street 1</street> does not exist:

  1. PowerShell should provide the name of the xml file where the <street>Baker street 1</street> path is not added.

  2. I need to update the <street>Baker street 1</street> in the 2 xml file.

I managed to get the output for 1st scenario

Get-ChildItem -File -Path C:Desktop\Path1\XML\*.* |
  ForEach-Object {
    [pscustomobject] @{
      HasCRLF = (Get-Content -Raw -LiteralPath $_.FullName).Contains("<street>Baker street 1</street>")
      Name = $_.Name
      FullName = $_.FullName
    }
  }  
  
  
HasCRLF Name     FullName                     
------- ----     --------                     
  False Jack.xml C:\Desktop\Path1\XML\Jack.xml
   True Joe.xml  C:\Desktop\Path1\XML\Joe.xml 
  False Ryan.xml C:\Desktop\Path1\XML\Ryan.xml

Need your help to add the missing info to the xml file.

Upvotes: 0

Views: 920

Answers (1)

Theo
Theo

Reputation: 61168

Iterate through the path where the xml files can be found and load each file as XmlDocument. Then the easiest would be to use the 'dot' notation to see if 'Baker street 1' can be found.

Get-ChildItem -Path 'C:\Desktop\Path1\XML' -Filter '*.xml' -File |
    ForEach-Object {
        # get all content as XML. Use this syntax, so you will get the encoding right
        $xml = [System.XML.XMLDocument]::new()
        $xml.Load($_.FullName)
        [PsCustOmobject] @{
            HasStreet = ($xml.addresses.address.street -eq 'Baker street 1')
            Name      = $_.Name
            FullName  = $_.FullName
        }
    } 

Using 'dot' syntax works case-insensitive, so $xml.Addresses.Address.Street is also fine as well as BaKeR StReEt 1

Output:

HasStreet Name     FullName        
--------- ----     --------        
    False Jack.xml D:\Test\Jack.xml
     True Joe.xml  D:\Test\Joe.xml 
    False Ryan.xml D:\Test\Ryan.xml

If you need to add the missing <street> tag to the files that do not have it, you can do this:

Get-ChildItem -Path 'C:\Desktop\Path1\XML' -Filter '*.xml' -File |
    ForEach-Object {
        # get all content as XML. Use this syntax, so you will get the encoding right
        $xml = [System.XML.XMLDocument]::new()
        $xml.Load($_.FullName)
        if (!$xml.addresses.address.street) {
            Write-Host "Adding node '<street>Baker street 1</street>' to file $($_.FullName)" 
            $streetNode = $xml.CreateElement('street')
            $streetNode.InnerText = 'Baker street 1'
            [void]$xml.addresses.address.AppendChild($streetNode)  # or use PrependChild() if <street> must come on top
            $xml.Save($_.FullName)
        }
    } 

Upvotes: 2

Related Questions