0

I will use this sample data as an example:

<?xml version="1.0"?>
<catalog>
   <book id="bk101">
      <author>Gambardella, Matthew</author>
      <title>XML Developer's Guide</title>
      <genre>Computer</genre>
      <price>44.95</price>
      <publish_date>2000-10-01</publish_date>
      <description>An in-depth look at creating applications 
      with XML.</description>
   </book>
   <book id="bk102">
      <author>Ralls, Kim</author>
      <title>Midnight Rain</title>
      <genre>Fantasy</genre>
      <price>5.95</price>
      <publish_date>2000-12-16</publish_date>
      <description>A former architect battles corporate zombies, 
      an evil sorceress, and her own childhood to become queen 
      of the world.</description>
   </book>
</catalog>

Link to data: https://learn.microsoft.com/en-us/previous-versions/windows/desktop/ms762271(v=vs.85)

Lets say I want to query the author and price

[xml]$XmlFileObj = Get-Content 'C:\Users\David\Documents\XmlSample.dtsx'

$XmlFileObj | Select-Xml -XPath "/catalog/book/author | /catalog/book/price "  | Select-Object -ExpandProperty Node

The result is:

#text               
-----               
Gambardella, Matthew
44.95               
Ralls, Kim          
5.95   

What if I want the result to look like:

#col1; col2               
-----               
Gambardella, Matthew; 44.95               
Ralls, Kim ; 5.95   

Or something like this in a table form...

xhr489
  • 1,957
  • 13
  • 39

1 Answers1

1

Instead of extracting the <author> and <price> nodes separately, use Select-Xml to enumerate the common ancestor - the <book> node - and then select the author and price nodes directly from each:

$XmlFileObj |Select-Xml '/catalog/book' |Select -ExpandProperty Node |Select author,price

If you want to filter based on descendant node values, you can either use an XPath predicate (//node/selector[predicate goes here]):

# This will return the author and price, but only of "Midnight Rain" 
$XmlFileObj |Select-Xml '/catalog/book[genre = "Fantasy"]' |Select -ExpandProperty Node |Select author,price

If you can't find an appropriate XPath function or operator, you can also take advantage of PowerShell's built-in XML adapter just like we do to extract author and price - from Select-Object's (or any other cmdlet's) perspective, their just properties like on any other object:

# This will return the author and price, but only of "Midnight Rain" 
$XmlFileObj |Select-Xml '/catalog/book' |Select -ExpandProperty Node |Where genre -eq Fantasy |Select author,price
Mathias R. Jessen
  • 157,619
  • 12
  • 148
  • 206
  • Great, thanks. where can I read more about this, what should I search for? – xhr489 Sep 20 '20 at 21:04
  • @David about what? XPath? – Mathias R. Jessen Sep 20 '20 at 21:04
  • Yes Xpath in PowerShell, and also PowerShell generally. – xhr489 Sep 20 '20 at 21:06
  • When I serarch the internet it seems a bit confusing and I want to build a better foundation in PowerShell and Xpath – xhr489 Sep 20 '20 at 21:08
  • 1
    @David Not sure there's much too it other than "`Select-Xml` allows you to use XPath selectors to select elements of an XML document". The fundamental lesson to take away here is basically "don't split relational data into disjoint pieces if you want to retain their relationships" - which applies pretty universally to PowerShell, not just in the context of XPath/XML :) – Mathias R. Jessen Sep 20 '20 at 21:09
  • How come select is not in this list at the lhs of the page? https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object?view=powershell-7 – xhr489 Sep 20 '20 at 21:16
  • There are only select-object but not select? How could I have known to use select? – xhr489 Sep 20 '20 at 21:17
  • 1
    @David Sorry for the ambiguity, `Select` _is_ `Select-Object` - `Select` is just an alias – Mathias R. Jessen Sep 20 '20 at 21:22
  • Hi, what if I then want to filter a row? – xhr489 Sep 21 '20 at 10:21
  • Thanks, very helpful! I have a new short question here. https://stackoverflow.com/questions/63990647/get-only-content-in-result-and-not-the-frame-powershell – xhr489 Sep 21 '20 at 10:40
  • Hi, how can I only select the `#text`column? – xhr489 Sep 21 '20 at 13:28
  • If you have another question, feel free to [ask](http://stackoverflow.com/questions/ask) – Mathias R. Jessen Sep 21 '20 at 13:29
  • Thanks, done: https://stackoverflow.com/questions/63993409/how-to-select-the-text-column-in-powershell – xhr489 Sep 21 '20 at 13:34
  • Hi can you please look at this question: https://stackoverflow.com/questions/63994136/update-xml-file-with-namespace-in-element-names-powershell – xhr489 Sep 21 '20 at 14:17