Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml 如何为不同的父节点选择具有相同名称的所有节点?_Xml_Xslt_Xpath - Fatal编程技术网

Xml 如何为不同的父节点选择具有相同名称的所有节点?

Xml 如何为不同的父节点选择具有相同名称的所有节点?,xml,xslt,xpath,Xml,Xslt,Xpath,假设我有以下xml: <root> <person> <name>John</name> </person> <children> <person> <name>Jack</name> </person> </children> </root> 约翰 杰克 可以同时选择两个人吗?假设我不知道另一个

假设我有以下xml:

<root>
  <person>
    <name>John</name>
  </person>
  <children>
    <person>
      <name>Jack</name>
    </person>
  </children>
</root>

约翰
杰克
可以同时选择两个人吗?假设我不知道另一个人在“子女”标签中,他们很可能在“配偶”标签中或完全不同的东西中,也可能在另一个孩子中。我知道我需要的所有人都在根标签中(不一定是文档根)

将两者匹配,无论它们在xml树中的何处

/
从当前节点选择文档中与所选内容匹配的节点,无论这些节点位于何处()

或者您可以使用:

根//人

因此,您只能在根元素中搜索person,您可以使用

//person

要在文档中查找任何
person
元素,但要小心-某些xsl处理器(如Microsoft)在大型
xml
文档中使用双斜杠的性能可能很差,因为文档中的所有节点都需要评估

编辑:
如果您知道“person”只有两条路径,那么您可以完全避免使用
/

<xsl:for-each select="/root/person | /root/children/person">
    <outputPerson>
        <xsl:value-of select="name/text()" />
    </outputPerson>
</xsl:for-each>

或命名空间不可知:

<xsl:for-each select="/*[local-name()='root']/*[local-name()='person'] 
  | /*[local-name()='root']/*[local-name()='children']/*[local-name()='person']">

正如nonnb所述,双斜杠在大型xml文档上的性能很差

因此,
//name
可以做到这一点,但可能会带来更多您期望的元素。 另外,想象一下,在根元素中,您有一些元素不是Person,这些元素可能有名为name的后代元素,根据您不想提出的问题,
//name
将提出这些元素

您应该将上下文节点仿射为max,这样XPath在性能方面将是最优的

对于这个精确的文档,我将使用

/root/descendant::person/name

希望有帮助,

在Petar Ivanov的回答中,
/
的定义是错误的

以下是中的正确定义:

/
/genderant或self::node()/


@Petre:始终仅从规范性来源提供任何定义。在您的回答中,XPath pseude运算符
/
的“定义”是错误的。w3schools因此类垃圾而臭名昭著。表中出现此定义的两个“表达式”不是偶数表达式。而且,OP要求的是
person
元素,而不是
name
元素。遗憾的是,这个答案被接受了。+1,有用的建议。不过,我要提醒大家,在大型xml文档上,双斜杠的性能很差,这取决于XSLT/XPath处理器。这是一个非常常见的操作,一个好的处理器通过元素名来构建索引,使之非常快。我假设您所说的
name
是指您要查找的元素的名称,即
person
。OP实际上并不是在寻找名为
name
@Lars-thx的元素作为反馈-outputPerson只是给OP举个例子-他没有给出输出xml模式。我在BizTalk 2009 Maps中使用//时有一段不好的经历-处理~100MB的文档会增加CPU使用率。就我而言,我只是在偷懒——用完整路径替换//避免了这个问题,而“no//”现在是我们BizTalk映射的编码标准。我的一些在XQuery内部工作的朋友告诉我,有一段时间,许多引擎(包括他们的引擎)的//运行缓慢,显式路径更快。他们中的一些人告诉我,现在他们已经改变了他们的内部代表性,事实正好相反,他们希望避免//的想法不会传播得如此广泛。因此,性能的铁律仍然适用:如果对您有影响,请在运行处理器的数据上衡量您的替代解决方案,并遵循每一条一般规则,即使是来自消息灵通人士,作为有趣的民间传说。@C.M.Sperberg-McQueen谢谢-我以后会听取您的建议并相应地进行资格认证。
后代:
在性能上并不比
/
好。实际上,
/
只是
/genderant或self::node()/
的缩写。因此,您建议的表达式相当于
/root//person/name
。但我不是至少没有加载person吗?我知道它不会有太大的变化,但从语法上来说,它感觉更准确——据我所说。不知道你在问什么。如果你问
/root//person/name
是否比
/root//person
表现更好,似乎不太可能:处理器必须首先找到
/root
的所有
person
元素,然后找到每个人的子
name
元素。@\u Thijs Wouters:你接受了一个错误的答案。@nonnb的答案是正确的。
<xsl:for-each select="/*[local-name()='root']/*[local-name()='person'] 
  | /*[local-name()='root']/*[local-name()='children']/*[local-name()='person']">
/root/descendant::person/name