Working with XML Files
Accessing an XML File
Section titled “Accessing an XML File”<!-- file.xml --><people> <person id="101"> <name>Jon Lajoie</name> <age>22</age> </person> <person id="102"> <name>Lord Gaben</name> <age>65</age> </person> <person id="103"> <name>Gordon Freeman</name> <age>29</age> </person></people>Loading an XML File
To load an XML file, you can use any of these:
# First Method$xdoc = New-Object System.Xml.XmlDocument$file = Resolve-Path(".\file.xml")$xdoc.load($file)
# Second Method[xml] $xdoc = Get-Content ".\file.xml"
# Third Method$xdoc = [xml] (Get-Content ".\file.xml")Accessing XML as Objects
PS C:\> $xml = [xml](Get-Content file.xml)PS C:\> $xml
PS C:\> $xml.people
person--------{Jon Lajoie, Lord Gaben, Gordon Freeman}
PS C:\> $xml.people.person
id name age-- ---- ---101 Jon Lajoie 22102 Lord Gaben 65103 Gordon Freeman 29
PS C:\> $xml.people.person[0].nameJon Lajoie
PS C:\> $xml.people.person[1].age65
PS C:\> $xml.people.person[2].id103Accessing XML with XPath
PS C:\> $xml = [xml](Get-Content file.xml)PS C:\> $xml
PS C:\> $xml.SelectNodes("//people")
person--------{Jon Lajoie, Lord Gaben, Gordon Freeman}
PS C:\> $xml.SelectNodes("//people//person")
id name age-- ---- ---101 Jon Lajoie 22102 Lord Gaben 65103 Gordon Freeman 29
PS C:\> $xml.SelectSingleNode("people//person[1]//name")Jon Lajoie
PS C:\> $xml.SelectSingleNode("people//person[2]//age")65
PS C:\> $xml.SelectSingleNode("people//person[3]//@id")103Accessing XML containing namespaces with XPath
PS C:\> [xml]$xml = @"<ns:people xmlns:ns="http://schemas.xmlsoap.org/soap/envelope/"> <ns:person id="101"> <ns:name>Jon Lajoie</ns:name> </ns:person> <ns:person id="102"> <ns:name>Lord Gaben</ns:name> </ns:person> <ns:person id="103"> <ns:name>Gordon Freeman</ns:name> </ns:person></ns:people>"@
PS C:\> $ns = new-object Xml.XmlNamespaceManager $xml.NameTablePS C:\> $ns.AddNamespace("ns", $xml.DocumentElement.NamespaceURI)PS C:\> $xml.SelectNodes("//ns:people/ns:person", $ns)
id name-- ----101 Jon Lajoie102 Lord Gaben103 Gordon FreemanCreating an XML Document using XmlWriter()
Section titled “Creating an XML Document using XmlWriter()”# Set The Formatting$xmlsettings = New-Object System.Xml.XmlWriterSettings$xmlsettings.Indent = $true$xmlsettings.IndentChars = " "
# Set the File Name Create The Document$XmlWriter = [System.XML.XmlWriter]::Create("C:\YourXML.xml", $xmlsettings)
# Write the XML Decleration and set the XSL$xmlWriter.WriteStartDocument()$xmlWriter.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='style.xsl'")
# Start the Root Element$xmlWriter.WriteStartElement("Root")
$xmlWriter.WriteStartElement("Object") # <-- Start <Object>
$xmlWriter.WriteElementString("Property1","Value 1") $xmlWriter.WriteElementString("Property2","Value 2")
$xmlWriter.WriteStartElement("SubObject") # <-- Start <SubObject> $xmlWriter.WriteElementString("Property3","Value 3") $xmlWriter.WriteEndElement() # <-- End <SubObject>
$xmlWriter.WriteEndElement() # <-- End <Object>
$xmlWriter.WriteEndElement() # <-- End <Root>
# End, Finalize and close the XML Document$xmlWriter.WriteEndDocument()$xmlWriter.Flush()$xmlWriter.Close()Output XML File
<?xml version="1.0" encoding="utf-8"?><?xml-stylesheet type='text/xsl' href='style.xsl'?><Root> <Object> <Property1>Value 1</Property1> <Property2>Value 2</Property2> <SubObject> <Property3>Value 3</Property3> </SubObject> </Object></Root>Adding snippits of XML to current XMLDocument
Section titled “Adding snippits of XML to current XMLDocument”Sample Data
Section titled “Sample Data”XML Document
Section titled “XML Document”First, let’s define a sample XML document named “books.xml” in our current directory:
New Data
Section titled “New Data”What we want to do is add a few new books to this document, let’s say Patriot Games by Tom Clancy (yes, I’m a fan of Clancy’s works ^__^) and a Sci-Fi favourite: The Hitchhiker’s Guide to the Galaxy by Douglas Adams mainly because Zaphod Beeblebrox is just fun to read.
Somehow we’ve acquired the data for the new books and saved them as a list of PSCustomObjects:
Templates
Section titled “Templates”Now we need to define a few skeleton XML structures for our new data to go into. Basically, you want to create a skeleton/template for each list of data. In our example, that means we need a template for the book, characters, and publishers. We can also use this to define a few default values, such as the value for the film tag.
We’re done with set-up.
Adding the new data
Section titled “Adding the new data”Now that we’re all set-up with our sample data, let’s add the custom objects to the XML Document Object.
We can now write our XML to disk, or screen, or web, or wherever!
Profit
Section titled “Profit”While this may not be the procedure for everyone I found it to help avoid a whole bunch of [void]$xml.SelectSingleNode("/complicated/xpath/goes[here]").AppendChild($xml.CreateElement("newElementName") followed by $xml.SelectSingleNode("/complicated/xpath/goes/here/newElementName") = $textValue
I think the method detailed in the example is cleaner and easier to parse for normal humans.
Improvements
Section titled “Improvements”It may be possible to change the template to include elements with children instead of breaking out each section as a separate template. You just have to take care to clone the previous element when you loop through the list.