Xpath选择祖先

时间:2018-03-10 10:55:08

标签: xml powershell xpath

我试图找到一个公式,根据它在XML层次结构中的位置为元素创建一个URL。

这是我的样本xml:

<Xml>
    <Site Url="http://mysite.abc">
        <Content></Content>
        <SubSites>
            <Site Url="/sub1">
                <Content></Content>
                <SubSites>
                    <Site Url="/sub2">
                        <Content></Content>
                        <SubSites>
                            <Site Url="/sub3">
                                <Content></Content>
                            </Site>
                        </SubSites>
                    </Site>
                </SubSites>
            </Site>
        </SubSites>
    </Site>
</Xml>

我在Powershell中有一个函数,它从顶部和每个内容递归地向下迭代。元素我想生成祖先Url值的串联。 所以它应该连续生成每个内容&#39;节点:

http://mysite.abc
http://mysite.abc/sub1
http://mysite.abc/sub1/sub2
http://mysite.abc/sub1/sub2/sub3

我现在用作开头: ($ Node =&#39;内容&#39;元素)

$Sites = $Node | Select-XML -XPath  "//ancestor::Site"

但对于每个$ Node,它会选择所有&#39; Site&#39;元素。 它期望它在xml结构中找到更多的祖先。

如果有人知道如何将值直接与Xpath连接起来会特别好,但对于初学者来说,我很乐意知道我当前的方法出了什么问题。

2 个答案:

答案 0 :(得分:4)

501将为您提供相对于树中任何节点( Code Eqpmnt 123 501 234 602 456 503 546 504 789 507 )的祖先//ancestor::Site节点。

使用Site仅抓取相对于当前节点(//)的祖先:

./ancestor::Site

答案 1 :(得分:1)

提供Mathias R. Jessen's helpful answer的替代方案(这可以很好地解释您的方法的问题并提供有效的解决方案):

由于 Site节点似乎始终是任何给定Content节点的节点,因此您只需参考具有Site路径组件的相应..节点。

此方法允许您立即处理整个文档

Select-Xml -LiteralPath sample.xml -XPath  "//Content/.." | ForEach-Object -Begin {
    $ancestralUrl = ''
  } -Process {
    $thisUrl = $_.Node.Url
    if ($thisUrl -match '^https?://') {
      $ancestralUrl = $thisUrl
    } else {
      $thisUrl = $ancestralUrl += $thisUrl
    }
    $thisUrl
  }

以上产量:

http://mysite.abc
http://mysite.abc/sub1
http://mysite.abc/sub1/sub2
http://mysite.abc/sub1/sub2/sub3

事实上,你甚至可以将上述方法与ancestor函数结合起来(虽然这里有点矫枉过正):

Select-Xml -LiteralPath sample.xml '//Content/ancestor::Site' | ForEach-Object -Begin {
  $ancestralUrl = ''
} -Process {
  $thisUrl = $_.Node.Url
  if ($thisUrl -match '^https?://') {
    $ancestralUrl = $thisUrl
  } else {
    $thisUrl = $ancestralUrl += $thisUrl
  }
  $thisUrl
}