假设我有这个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
两者都不会因某种原因而起作用。我怎样才能得到这些值?
答案 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'