通过PowerShell读取XML

时间:2017-08-30 10:00:52

标签: xml powershell

假设我有这个XML文件:

<?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>

现在我想用PowerShell阅读,例如:

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

$books = $xml.books.book.id

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

在循环中我想得到每本书的章节,所以我尝试了这个:

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

但这不起作用。所以我尝试了这个:

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

两者都不会因某种原因而起作用。我怎样才能得到这些值?

1 个答案:

答案 0 :(得分:1)

您的第一种方法不起作用,因为Select-Object允许您选择属性(chapters),但不能选择嵌套属性(chapters.chapter1)。您需要展开属性并级联cmdlet调用以获取子属性值:

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

您的第二种方法不起作用,因为您从$中省略了$xml,并且您没有正确的缩写Where-Object语法。如果您想使用简短Where-Object过滤器表示法<cmdlet> <property> <op> <value>而不使用当前对象变量($_):

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

否则你需要常规语法:

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

据说,没有一种方法非常优雅。对于您的示例场景,您只需使用点符号来获取所有<chapter1>值:

$xml.books.book.chapters.chapter1

如果您需要更多控制权,使用XPath expressions通常会更有效率,例如如果您想要所有图书ID的列表:

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

或者如果你想用ID&#34; book2&#34;选择书籍的第三章:

$id = 'book2'
$xml.SelectSingleNode("//book[@id='$id']/chapters/chapter3").'#text'