?
Solved

Powershell and XML question

Posted on 2014-01-14
2
Medium Priority
?
383 Views
Last Modified: 2014-01-15
Hi - Powershell newbie. I have the following XML sample. I need to iterate through it via powershell and run some powershell code at each level. I am able to reach any one of the items but have not been successfull in looping through each one. I could use a sample of how to do this. For this example - just printing the text of each element to the console would be fine so long as I can replace that code with the actual code I need to accomplish the goal.

Here is the sample file. There are some elements that are nested as shown.

<?xml version="1.0" encoding="utf-8"?>
<Locations>
  <!-- There can be multiple locations -->
  <Location>
      <Name>Location A</Name>

	<!-- There can be multiple Drawers per location -->	  
  <Drawers>
      <Drawer>
        <Name>Drawer 1</Name>
		<!-- There can be multiple Files per Drawer -->	
        <Files>
          <File>
            <Name>File 1</Name>
			<!-- There can be multiple Custom Variables anywhere -->
			<Attributes>	
				<Attribute>ID</Attribute>
				<Attribute>User Name</Attribute>
				<Attribute>Another Variable</Attribute>
			</Attributes>	
			<!-- There can be multiple Folders per File -->
			<!-- Folders can be nested -->				
            <Folder>
              <Name>Folder 1</Name>
			  <!-- There can be multiple Custom Variables anywhere -->	
				<Attribute>ID</Attribute>
				<Attribute>User Name</Attribute>
			  <!-- There can be multiple Documents per Folder -->	
              <Document>
                <Name>Document 1</Name>
				<!-- There can be multiple Custom Variables anywhere -->	
				<Attribute>ID</Attribute>
				<Attribute>User Name</Attribute>
              </Document>
              <Document>
                <Name>Document 2</Name>
              </Document>
              <Document>
                <Name>Document 2</Name>
              </Document>
              <Folder>
                <Name>Folder 1.1</Name>
				<Repeatable>True</Repeatable>
				<Attribute>ID</Attribute>
				<Attribute>User Name</Attribute>
                <Document>
                  <Name>Document 1.1</Name>
                </Document>
                <Document>
                  <Name>Document 1.2</Name>
                </Document>
                <Document>
                  <Name>Document 1.2</Name>
                </Document>
					<Folder>
						<Name>Folder 1.1.1</Name>
						<Document>
						  <Name>Document 1.1.1</Name>
						</Document>
						<Document>
						  <Name>Document 1.1.2</Name>
						</Document>
						<Document>
						  <Name>Document 1.1.2</Name>
						</Document>
					</Folder>
				</Folder>
            </Folder>
          </File>
		  <File>
            <Name>File 2</Name>
            <Folder>
              <Name>Folder 1</Name>
              <Document>
                <Name>Document 1</Name>
              </Document>
              <Document>
                <Name>Document 2</Name>
              </Document>
              <Document>
                <Name>Document 2</Name>
              </Document>
              <Folder>
                <Name>Folder 1.1</Name>
                <Document>
                  <Name>Document 1.1</Name>
                </Document>
                <Document>
                  <Name>Document 1.2</Name>
                </Document>
                <Document>
                  <Name>Document 1.2</Name>
                </Document>
				</Folder>
            </Folder>
          </File>
        </Files>        
      </Drawer>
	  <!-- The next drawer with similar files, folders and documents as the first. -->	
      <Drawer>
      </Drawer>
    </Drawers>
  </Location>
</Locations>

Open in new window

0
Comment
Question by:ckelsoe
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
2 Comments
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 2000 total points
ID: 39782369
Hi, have a look at this. I've put comments in to make clear where to add/change code, maybe overkill but anyway...

Let me know if you have any questions.
# settings

$xmlFile = ’sample.xml’

# functions

Function ProcessXmlDoc
{
Param ([xml] $xmlDoc)

    foreach ($locationNode in $xmlDoc.Locations.Location) {
        # put code that needs to be performed for every <Location> node here.
        Write-Host (“* Location Name={0}” -f $locationNode.Name)
        foreach ($drawerNode in $locationNode.Drawers.Drawer) {
            # additional code for <Drawer> nodes here
            Write-Host (“** Location Name={0}, Drawer Name={1}” -f $locationNode.Name,$drawerNode.Name)
            foreach ($fileNode in $drawerNode.Files.File) {
                # additional code for <File> nodes here
                Write-Host (“*** Location Name={0}, Drawer Name={1}, File Name={2}” -f $locationNode.Name,$drawerNode.Name,$fileNode.Name)
                RecurseFolders $fileNode
            }
        }
    }
}

Function RecurseFolders
{
Param ([system.xml.xmlelement] $folderNodeParam,[string] $FolderPath = "") # <File> node or <Folder> node, both can contain <Folder> nodes

    # construct "path" to current file/folder tree in the xml document
    if ($FolderPath -ne "") {
        $FolderPath = $FolderPath + "/" + $folderNodeParam.Name
    } else {
        $FolderPath = $folderNodeParam.Name
    }

    # additional code for <Folder> nodes here

    if ($folderNodeParam.Document) {
        # additional code for <Folder> nodes which contain <Document> nodes here
        foreach ($documentNode in $folderNodeParam.Document) {
            # additional code for <Document> nodes here
            Write-Host (“**** Document Name={0}, Folder Path={1}” -f $documentNode.Name,$FolderPath) # $folderNodeParam.Name
        }
    }
    if ($folderNodeParam.Folder) {
        # additional code for <Folder> nodes which contain <Folder> nodes here
        foreach ($folderNode in $folderNodeParam.Folder) {
            RecurseFolders $folderNode $FolderPath
        }
    }
}

#main code

ProcessXmlDoc (Get-Content -Path $xmlFile)

Open in new window

PS: I'm not overly experienced in PowerShell myself but thought it would be a nice experience to try solving it, got this far, saw no reply yet and decided to post as this should get you started at least.
0
 

Author Comment

by:ckelsoe
ID: 39783548
Hi Robert,

I am impressed! Thank you for the excellent example.

I have more to figure out but this code example is a great start. Thanks.
0

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Windows 10 came with  a lot of built in applications, Some organisations leave them there, some will control them using GPO's. This Article is useful for those who do not want to have any applications in their image (example:me).
A recent project that involved parsing Tableau Desktop and Server log files to extract reusable user queries for use in other systems. I chose to use PowerShell to gather the data, and SharePoint to present it...
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
Monitoring a network: how to monitor network services and why? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the philosophy behind service monitoring and why a handshake validation is critical in network monitoring. Software utilized …

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question