Search code examples
xmlpowershellfilecopynodes

PowerShell / XML - Copy xml file to folder according to node value


I'm fairly new to PowerShell but have used it in a limited capacity thus far.

So, here's my problem: I have 100,000's of xml files which contain a node that has a State value. I would like to use PowerShell to read the files then copy the files into their respective State folders. I can have the folders already created or have the PS script do it. Either would work but I would like to learn how to do both 1. copy the files to specific folders and 2. create the folders then copy the files to them.

Example:

XML1

<Member>
  <LastName>LASTNAME1</LastName>
  <FirstName>FIRSTNAME1</FirstName>
  <AddressParent>
    <Address>
      <Type>HOME1</Type>
      <Address1>123 STREET</Address1>
      <State>FL</State>
    </Address>
  </AddressParent>
</Member>

XML2

<Member>
  <LastName>LASTNAME2</LastName>
  <FirstName>FIRSTNAME2</FirstName>
  <AddressParent>
    <Address>
      <Type>HOME1</Type>
      <Address1>234 STREET</Address1>
      <State>NY</State>
    </Address>
  </AddressParent>
</Member>

To reiterate: I would like to read the files that exist in a single folder. Copy the files to their respective State folders according to the <State> node.

Also, there is more than 1 <State> node per XML file so I will need to use an absolute path (not sure if that's the correct term).

I want to thank you all in advance and any assistance you can provide is greatly appreciated.


Solution

  • Use Select-Xml to extract the first <State> node in each document, then move the file based on that:

    Get-ChildItem |Select-Xml -XPath '//State[1]' |ForEach-Object {
      $State = $_.Node.InnerText
    
      # Check to see if folder already exists, otherwise create it
      if(-not(Test-Path $State)){
        $null = mkdir $State
      }
    
      # Move the source file to the state folder
      Move-Item -LiteralPath $_.Path -Destination $State
    }
    

    The XPath predicate means:

    //           # Anywhere in the node tree
      State      # Find a <State> node
           [1]   # Select the one at position 1