我想从xml文件中提取所有窗口和所有视点节点中name-attributes的值。
<?xml version='1.0' encoding='utf-8' ?>
<workbook>
<windows>
<window class='dashboard' name='D1'>
<viewpoints>
<viewpoint name='V1'> </viewpoint>
<viewpoint name='V2'> </viewpoint>
<viewpoint name='V3'> </viewpoint>
</viewpoints>
</window>
<window class='dashboard' name='D2'>
<viewpoints>
<viewpoint name='V10'> </viewpoint>
<viewpoint name='V11'> </viewpoint>
</viewpoints>
</window>
</windows>
</workbook>
这是我写的代码:
[XML]$doc = get-content -path 'W:\Demo1.xml'
$objs = @()
$dashboards = $doc.SelectNodes("//window[@class = 'dashboard']")
foreach ($dashboard in $dashboards)
{
$worksheets = $dashboard.SelectNodes("//viewpoint[@name]")
foreach ($worksheet in $worksheets)
{
$obj = new-object psobject -prop @{Dashboard=$dashboard.name; Worksheet = $worksheet.name};
$objs += $obj;
}
}
$objs
我的期望:
dashboard worksheet D1 V1 D1 V2 D1 V3 D2 V10 D2 V11
我得到了什么:
dashboard worksheet D1 V1 D1 V2 D1 V3 D1 V10 D1 V11 D1 V14 D2 V1 D2 V2 D2 V3 D2 V10 D2 V11 D2 V14
这里有什么问题?结果与我对嵌套循环如何工作的理解完全矛盾。
答案 0 :(得分:2)
以/
字符开头的XPath意味着它将从文档根节点开始。要从上下文节点创建相对XPath,您需要在.
之前放置/
。
所以你的代码应该是:
[XML]$doc = get-content -path 'W:\Demo1.xml'
$objs = @()
$dashboards = $doc.SelectNodes("//window[@class = 'dashboard']")
foreach ($dashboard in $dashboards)
{
$worksheets = $dashboard.SelectNodes(".//viewpoint[@name]")
foreach ($worksheet in $worksheets)
{
$obj = new-object psobject -prop @{Dashboard=$dashboard.name; Worksheet = $worksheet.name};
$objs += $obj;
}
}
$objs
答案 1 :(得分:1)
您还可以简化并采用xpath
从信息中心窗口中选择所有viewpoint
个节点:
[XML]$doc = get-content -path 'W:\Demo1.xml'
$objs = @()
$worksheets = $doc.SelectNodes("//window[@class = 'dashboard']//viewpoint[@name]")
foreach ($worksheet in $worksheets)
{
$obj = new-object psobject -prop @{Dashboard=$worksheet.ParentNode.ParentNode.name; Worksheet = $worksheet.name};
$objs += $obj;
}
$objs
这是一个没有xpath
的解决方案:
[XML]$doc = get-content -path 'W:\Demo1.xml'
$objs = $doc.DocumentElement.windows.window | Where class -eq 'dashboard' | foreach {
$dashboardName = $_.name
$_.viewpoints.viewpoint | foreach {
new-object psobject -prop @{Dashboard=$dashboardName; Worksheet = $_.name}
}
}