【问题标题】:Select parent node based on attribute of current child node根据当前子节点的属性选择父节点
【发布时间】:2019-04-01 20:53:27
【问题描述】:

有很多关于根据子属性的值选择父节点的问题,但似乎都没有解决这种情况。

我有一些 XML:

<TABDISP>
  <HEADER ORDER="1" PROMPT="Next of kin" />
  <HEADER ORDER="2" PROMPT="Emergency contact" />
  <ROW ORDER="1" PROMPT="Family name">
    <FIELD ORDER="1" TYPE="TEXT" NAME="NKSurname" MANDATORY="N" />
    <FIELD ORDER="2" TYPE="TEXT" NAME="ECSurname" MANDATORY="N" />
  </ROW>
  <ROW ORDER="2" PROMPT="Forenames">
    <FIELD ORDER="1" TYPE="TEXT" NAME="NKForename" MANDATORY="N" />
    <FIELD ORDER="2" TYPE="TEXT" NAME="ECForename" MANDATORY="N" />
  </ROW>
</TABDISP>

从任何 FIELD 节点的上下文中,我想选择 @ORDER 属性匹配的 HEADER 节点(最终,我将提取与该字段相关的提示)。

我已经尝试过../../HEADER[@ORDER=./@ORDER](我没想到它会起作用,但它需要尝试),../../HEADER[@ORDER=self::node()/@ORDER],目前我想知道是否有合适的轴我可以使用,但到目前为止我还没有找到一个适当的函数,它返回我可以放入过滤器的原始 FIELD 上下文节点。

我错过了什么?

【问题讨论】:

  • 那么你已经有了特定ORDER的FIELD节点,还需要找到对应的HEADER节点吗?
  • 没错。我试图在单个表达式中执行此操作,而不必在一个表达式中读取值并使用先前保存的值构造第二个(对于上下文,我在 SQL Server 中使用它的 XML 工具执行此操作,所以不可能将其拆分为两个语句)。

标签: xml xpath


【解决方案1】:

最近有理由重新审视这个问题,答案分为两部分:

  1. 这在 XPath 1.0 中是不可能的。这个网站上的另一个问题完全回答了这个问题:XPath equivalent to current()

  2. 上面的答案对 SQL Server XML 没有帮助,但是通过进一步的实验,可以在 SQL Server 中执行相同的操作,如下所示:


declare @t xml = '<TABDISP>
  <HEADER ORDER="1" PROMPT="Next of kin" />
  <HEADER ORDER="2" PROMPT="Emergency contact" />
  <ROW ORDER="1" PROMPT="Family name">
    <FIELD ORDER="1" TYPE="TEXT" NAME="NKSurname" MANDATORY="N" />
    <FIELD ORDER="2" TYPE="TEXT" NAME="ECSurname" MANDATORY="N" />
  </ROW>
  <ROW ORDER="2" PROMPT="Forenames">
    <FIELD ORDER="1" TYPE="TEXT" NAME="NKForename" MANDATORY="N" />
    <FIELD ORDER="2" TYPE="TEXT" NAME="ECForename" MANDATORY="N" />
  </ROW>
</TABDISP>';

select field.xmlnode.value('(./@NAME)[1]', 'nvarchar(20)'), 
        field.xmlnode.value('(./@ORDER)[1]', 'int'), 
        header.xmlnode.value('(./@PROMPT)[1]', 'nvarchar(50)'),
        header.xmlnode.value('(./@ORDER)[1]', 'int')
    from @t.nodes('//FIELD') field(xmlnode)
        cross apply @t.nodes('//HEADER') header(xmlnode)
    where field.xmlnode.value('(./@ORDER)[1]', 'int') = header.xmlnode.value('(./@ORDER)[1]', 'int')

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多