【问题标题】:Does node-set() have an ancestor node?node-set() 是否有祖先节点?
【发布时间】:2015-06-04 02:19:49
【问题描述】:

我觉得,这是一个基本的 XSLT 问题。据我了解,节点集本身就是数据结构。从 node-set() 我无法导航到集合之外的任何节点。即我无法到达父级、xml 的开头或其兄弟姐妹。是这样吗?

有没有办法获得节点集的父节点()

代码

<neighbourhood>
<parent name = "xyz">
<child address=10> a </child>
<child address=10> b </child>
<child address=15> c </child>
</parent>
</neighbourhood>

我有一组子节点。我需要消除具有重复“地址”的节点。 可以有 n 个“父级”和 m 个“子级”,并且“子级”可以有一个祖父节点。

最好和合乎逻辑的方法可能是每个父母都去处理他们的孩子。但是,它是一个现有的代码库,这是一个过于简单的例子。我不想通过触摸调用函数和其他模板来破坏太多东西。

所以,我的问题是我是否可以使用我拥有的“子”节点集获得“父”

感谢您的所有回复

【问题讨论】:

  • 快速提问 - 为什么需要?我从来不需要这样做,我想知道是否有更好的方法来做你正在做的任何事情。
  • 是的!我也这么认为。我只是不确定正确的方法可能是什么。我已经用更多细节更新了这个问题。我确实找到了解决问题的方法,但这可能不是最好的方法
  • 恐怕你的问题没有以前那么清楚了。如果您的目标是消除重复,那么 - 假设这是关于 XSLT 1.0 - 为此目的使用 Muenchian grouping,或者 - 如果您的处理器支持它 - EXSLT set:distinct() 函数。在任何情况下,都不清楚在这种情况下什么是“节点集”,以及这种集的祖先将在其中扮演什么角色。

标签: xslt


【解决方案1】:

node-set() 有祖先节点吗?

node-set() 是一个(扩展)函数——不是一个节点。函数不能有祖先,因为它不是节点。

我想问题中的"node-set()" 是指xxx:node-set() 函数返回的值(其中前缀“xxx”绑定到特定于供应商的命名空间)。如果是这样,这是想要的答案:

根据定义,xxx:node-set()函数返回一个临时树的document-node()(在XPath 1.0中也称为root-node),它是通过将RTF(Result Tree Fragment ),作为唯一参数传递给此函数。

根据定义,文档节点位于文档层次结构的顶部,并且是 XML 文档中唯一没有父节点的节点。

因此,被调用的xxx:node-set() 函数返回的节点没有任何祖先

从 node-set() 我无法导航到集合之外的任何节点。即我无法到达父级、xml 的开头或其兄弟姐妹。是这样吗?

是的,如果不调用从另一个文档返回节点的另一个函数(例如标准 XPath 函数 id() 或标准 XSLT 函数 document()),或引用变量/参数,则无法导航到仅使用 XPath 定位步骤从另一个文档中获取节点。

有没有办法获得节点集的父节点()

不,xxx:node-set() 函数返回的节点是文档节点,并且文档节点没有父(或任何其他祖先)节点。

【讨论】:

  • 感谢您的确认
【解决方案2】:

不要混淆节点集和node-set()s。

这是什么意思?嗯,节点集是一组节点。在正常的、未扩展的 XSLT 1.0 中,这意味着从输入文档中选择节点。如果我这样做:

<!-- a node set -->
<xsl:variable name="my-node-set"
    select="/indoc/level1/level2"/>

变量$my-node-set 包含一组level2 节点,但这些节点仍然存在于输入文档中。如果我随后像这样执行for-each

<nodeset-from-indoc>
    <xsl:for-each select="$my-node-set/level3">
         <parent>
             <xsl:value-of select="local-name(..)"/>
         </parent>
         <grandparent>
             <xsl:value-of select="local-name(../..)"/>
         </grandparent>
     </xsl:for-each>
 </nodeset-from-indoc>

得到每个节点的父母和祖父母的名字:

<nodeset-from-indoc>
    <parent>level2</parent><grandparent>level1</grandparent>
    <parent>level2</parent><grandparent>level1</grandparent>
    <parent>level2</parent><grandparent>level1</grandparent>
</nodeset-from-indoc>

但是,如果我将节点硬编码到变量中:

<!-- a result-tree fragment -->
<xsl:variable name="my-rtf">
    <level2>
        <level3>1</level3>
    </level2>
    <level2>
        <level3>2</level3>
    </level2>
    <level2>
        <level3>3</level3>
    </level2>
</xsl:variable>

不是一个节点集,而是一个结果树片段,因为它们不是从输入文档中选择的。结果树片段的问题是您不能在它们上使用 XPath。例如,我不能这样做:

<xsl:for-each select="$my-rtf/level3">

这就是node-set() 函数的用武之地。它是XSLT 1.0 的扩展,它来自一些扩展命名空间,具体取决于您的XSLT 处理器。许多处理器选择在 EXSLT 定义的命名空间中实现这一点。

正如 Dmitre 所指出的,node-set() 函数返回一个临时树的魔法文档节点,允许您使用 XPath。 但是,这会导致选择需要完成的方式发生微妙的变化。由于魔术文档节点,我必须在我的选择中包含level2

<nodeset-from-rtf>
    <xsl:for-each select="exsl:node-set($my-rtf)/level2/level3">
        <parent>
            <xsl:value-of select="local-name(..)"/>
        </parent>
        <grandparent>
            <xsl:value-of select="local-name(../..)"/>
        </grandparent>
    </xsl:for-each>
</nodeset-from-rtf>

在这种情况下,level3 节点将有父母,但没有祖父母:

<nodeset-from-rtf>
    <parent>level2</parent><grandparent/>
    <parent>level2</parent><grandparent/>
    <parent>level2</parent><grandparent/>
</nodeset-from-rtf>

【讨论】:

  • 我应该更具体一些。正如 Dimitre 猜测的那样,我正在谈论在 RTF 节点上工作的 node-set() 函数。但是,谢谢你的解释
【解决方案3】:

节点集是一组节点。节点集中的每个节点都有祖先。节点集本身没有。如果 $NS 是一个节点集,您可以执行 $NS/ancestor::node():这将为您提供节点集中所有节点的所有祖先,并消除重复项。

【讨论】:

  • “节点集本身没有”感谢 Michael 确认这一点。
猜你喜欢
  • 2018-10-07
  • 1970-01-01
  • 1970-01-01
  • 2010-09-17
  • 1970-01-01
  • 2012-09-07
  • 1970-01-01
  • 1970-01-01
  • 2022-11-17
相关资源
最近更新 更多