Solved

Powershell and XML question

Posted on 2014-01-14
2
370 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
2 Comments
 
LVL 35

Accepted Solution

by:
Robert Schutt earned 500 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

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

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

This is a PowerShell web interface I use to manage some task as a network administrator. Clicking an action button on the left frame will display a form in the middle frame to input some data in textboxes, process this data in PowerShell and display…
How to sign a powershell script so you can prevent tampering, and only allow users to run authorised Powershell scripts
This is a video describing the growing solar energy use in Utah. This is a topic that greatly interests me and so I decided to produce a video about it.
With Secure Portal Encryption, the recipient is sent a link to their email address directing them to the email laundry delivery page. From there, the recipient will be required to enter a user name and password to enter the page. Once the recipient …

911 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now