[xml] $xml = @" 12
"@
This is a basic XML structure with 1 root node (nodes), two node elements, each of which have two child elements (a and b, and, c and d). Select-Xml has two key parameters: 1) XPath and 2) Xml. These alone can give you a functional use of Select-Xml. So, here we will explore three different uses of Select-Xml that yield identical results:all return the folowing:Select-Xml -XPath "/nodes/node/a" -Xml $xmlSelect-Xml -XPath "//node/a" -Xml $xmlSelect-Xml -XPath "//a" -Xml $xml
When you use the // syntax, as opposed to the / syntax, it essential starts searching at that depth as if it were the root. So, to search from the node element as if it were the absolute root, I use //node/a. Similarly, to search from a as if it were the root node I would use //a. So, if you have an XML structure you can use double slashes and start from there to search across all nodes. This was useful to realize.Node Path Pattern---- ---- -------a InputStream /nodes/node/a
Next in my explorations was the use of the brackets, []. In XPath, as indicated in the link below.
http://www.w3schools.com/xpath/xpath_syntax.aspthe notation of [a=1] is used to match nodes where the attribute (or element) a has a value of 1. In this case, the syntax, can be //nodes/node[a=1] or //node[a=1] based on what was covered in the previous paragraph. It is important to note this is useful to narrowing down a set of nodes to a specific item (or set of items) and increase precision when matching. Similar to what was shown int he last paragraph, the two following statements are equivalent,
Both produce:# To find specific elementsSelect-Xml -XPath "//node[a=1]" -Xml $xmlSelect-Xml -XPath "/nodes/node[a=1]" -Xml $xml
What is important here is that it focuses in on specific nodes instead of all nodes with the element a.Node Path Pattern---- ---- -------node InputStream /nodes/node[a=1]
Next, is the use of the .SelectSingleNode() method. This approach is useful for finding singular resulting nodes. Building on our previous query, we can use this approach to find the node where c = 3,
The cool thing about the use of Select-Object, in conjunction with .SelectSingleNode, is that you can see the full scope of what is returned by the cmdlet. For example, the above returns this:# To remove specific elements - in this case,# the node that has an element c with a value 3# Demonstrate which node is selected with this# XPath query with Select *$xml.SelectSingleNode("//nodes/node[c=3]") |Select-Object *
If you never pipelined the output to Select-Object * you may never realize there are so many options from which one can choose after using the Select-Xml cmdlet. Addtionally, the OuterXml indicates the larger picture of what branch of the XML structure you are zeroing in on. Similarly, the InnerXml property shows the immediate element.id : 2c : 3d : 4Name : nodeLocalName : nodeNamespaceURI :Prefix :NodeType : ElementParentNode : nodesOwnerDocument : #documentIsEmpty : FalseAttributes : {id}HasAttributes : TrueSchemaInfo : System.Xml.XmlNameInnerXml :3 4 InnerText : 34NextSibling :PreviousSibling : nodeValue :ChildNodes : {c, d}FirstChild : cLastChild : dHasChildNodes : TrueIsReadOnly : FalseOuterXml :3 4 BaseURI :
One of the last items I want to highlight is how to remove a single node. Say, for instance, I want to remove the node where c = 3. Extending the .SelectSingleNode() method call from the previous step, I could call this:
After running this, we can look at $xml and see what remains.# Remove node identified in previous step$xml.nodes.RemoveChild($xml.SelectSingleNode("//nodes/node[c=3]"))
The output from this is somewhat lengthy,# See what remains from original XML structure$xml |Select-Object *
However, as noted by the OuterXml property, the remaining branches of the original $xml structure isnodes : nodesNodeType : DocumentParentNode :DocumentType :Implementation : System.Xml.XmlImplementationName : #documentLocalName : #documentDocumentElement : nodesOwnerDocument :Schemas : System.Xml.Schema.XmlSchemaSetXmlResolver :NameTable : System.Xml.NameTablePreserveWhitespace: FalseIsReadOnly : FalseInnerText :InnerXml :12 SchemaInfo : System.Xml.Schema.XmlSchemaInfoBaseURI :Value :ChildNodes : {nodes}PreviousSibling :NextSibling :Attributes :FirstChild : nodesLastChild : nodesHasChildNodes : TrueNamespaceURI :Prefix :OuterXml :12
There are a ton of other things we could explore with regards to XML and PowerShell, but, these simple tasks offer a simple set of how to steps that help to show XML is not impossible to figure out. It just takes some experimentation and reading.