1

Assume I have this XML file:

<?xml version="1.0" encoding="UTF-8"?>
<books>
  <book id="book1">
    <chapters>
      <chapter1>Begin</chapter1>
      <chapter2>mid</chapter2>
      <chapter3>end</chapter3>
    </chapters>
    <pages>352</pages>
  </book>
  <book id="book2">
    <chapters>
      <chapter1>woop</chapter1>
      <chapter2>doop</chapter2>
      <chapter3>goop</chapter3>
    </chapters>
    <pages>761</pages>
  </book>
</books>

Now I want to read this with PowerShell, e.g.:

$file = "C:\path\books.xml"
$xml = [xml](Get-Content $file)

$books = $xml.books.book.id

foreach ($book in $books) {
    ...
}

In the loop I want to get the chapters of each book, so I tried this:

$xml.books.book | ? {$_.id -eq $book} | select chapters.chapter1

but that didn't work. So I tried this instead:

(xml.books.book | where $_.id -eq $book).chapters.chapter1

Both won't work for some reason. How can I get these values?

1 Answer 1

1

Your first approach didn't work, because Select-Object lets you select properties (chapters), but not nested properties (chapters.chapter1). You'd need to expand the properties and cascade the cmdlet calls to get the child property values:

$xml.books.book |
    Where-Object {$_.id -eq $book} |
    Select-Object -Expand chapters |
    Select-Object -Expand chapter1

Your second approach didn't work, because you omitted the $ from $xml and you didn't get the abbreviated Where-Object syntax right. If you want to use short Where-Object filter notation it's <cmdlet> <property> <op> <value> without the current object variable ($_):

($xml.books.book | Where-Object id -eq $book).chapters.chapter1

otherwise you need the regular syntax:

($xml.books.book | Where-Object {$_.id -eq $book}).chapters.chapter1

With that said, none of the approaches is very elegant. For your example scenario you could simply use dot-notation to get all <chapter1> values:

$xml.books.book.chapters.chapter1

If you need more control it's usually more efficient to use XPath expressions, though, e.g. if you want a list of all book IDs:

$xml.SelectNodes('//book/@id') | Select-Object -Expand '#text'

or if you want to select the third chapter of the book with the ID "book2":

$id = 'book2'
$xml.SelectSingleNode("//book[@id='$id']/chapters/chapter3").'#text'
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks! :) i tried the 3rd option and it worked. Grazi mille!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.