?
Solved

Powershell and XML question

Posted on 2014-01-14
2
Medium Priority
?
384 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).
Auditing domain password hashes is a commonly overlooked but critical requirement to ensuring secure passwords practices are followed. Methods exist to extract hashes directly for a live domain however this article describes a process to extract u…
Video by: ITPro.TV
In this episode Don builds upon the troubleshooting techniques by demonstrating how to properly monitor a vSphere deployment to detect problems before they occur. He begins the show using tools found within the vSphere suite as ends the show demonst…
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…

649 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