Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/xpath/2.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
Xslt 第一个元素的XPATH,该元素的名称在其他一些元素的名称中_Xslt_Xpath_Xpath 2.0 - Fatal编程技术网

Xslt 第一个元素的XPATH,该元素的名称在其他一些元素的名称中

Xslt 第一个元素的XPATH,该元素的名称在其他一些元素的名称中,xslt,xpath,xpath-2.0,Xslt,Xpath,Xpath 2.0,得到我想要的: 红色,的值 有更直接的方法吗?您可以像这样使用key()函数 当此输入文档… <xsl:variable name="choices.str"> <xsl:for-each select="choices/*"> <xsl:text> </xsl:text><xsl:value-of select="concat(name(),' ')"/> </xsl:for-each> &

得到我想要的:

红色
的值

有更直接的方法吗?

您可以像这样使用key()函数

当此输入文档…

<xsl:variable name="choices.str">
    <xsl:for-each select="choices/*">
        <xsl:text> </xsl:text><xsl:value-of select="concat(name(),' ')"/>
    </xsl:for-each>
</xsl:variable>
<xsl:apply-templates select="choice/*[contains($choices.str,name())][1]"/>
<t>
<choices>
   <sic  />
   <corr />
   <reg  />
   <orig />
</choices>
<choice>
   <corr>Red</corr>
   <sic>Blue</sic>
  </choice>
</t>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kChoices" match="choices/*" use="name()" />  

<xsl:template match="/">
  <xsl:variable name="first-choice" select="(*/choice/*[key('kChoices',name())])[1]" />
  <xsl:value-of select="$first-choice" />
  <xsl:text>, the value of &lt;</xsl:text>
  <xsl:value-of select="name( $first-choice)" />
  <xsl:text>&gt;</xsl:text>
</xsl:template>

</xsl:stylesheet>
备选案文2:

(*/choice/*[for $c in . return ../../choices/*[name()=name($c)]])[1]

I.使用XPath 2.0单行程序

(*/choice/*[some $c in ../../choices/* satisfies name($c)=name()])[1]
<t>
    <choices>
        <sic  />
        <corr />
        <reg  />
        <orig />
    </choices>
    <choice>
        <corr>Red</corr>
        <sic>Blue</sic>
    </choice>
</t>
<corr>Red</corr>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:key name="kChoiceByName" match="choice/*"
   use="boolean(/*/choices/*[name()=name(current())])"/>

 <xsl:template match="/">
  <xsl:copy-of select="/*/choice/*[key('kChoiceByName', true())][1]"/>
 </xsl:template>
</xsl:stylesheet>
根据以下XML文档计算此XPath表达式时(提供的文档,但已更正为格式良好的XML文档):


红色
蓝色
选择了正确的元素

(*/choice/*[some $c in ../../choices/* satisfies name($c)=name()])[1]
<t>
    <choices>
        <sic  />
        <corr />
        <reg  />
        <orig />
    </choices>
    <choice>
        <corr>Red</corr>
        <sic>Blue</sic>
    </choice>
</t>
<corr>Red</corr>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:key name="kChoiceByName" match="choice/*"
   use="boolean(/*/choices/*[name()=name(current())])"/>

 <xsl:template match="/">
  <xsl:copy-of select="/*/choice/*[key('kChoiceByName', true())][1]"/>
 </xsl:template>
</xsl:stylesheet>
红色

II。XSLT1.0(无键!):

<corr>Red</corr>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vNames">
  <xsl:for-each select="/*/choices/*">
   <xsl:value-of select="concat(' ', name(), ' ')"/>
  </xsl:for-each>
 </xsl:variable>

 <xsl:template match="/">
  <xsl:copy-of select=
  "/*/choice/*
         [contains($vNames, concat(' ', name(), ' '))]
           [1]"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一XML文档(如上)时,再次选择正确的元素(并复制到输出):

<corr>Red</corr>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:variable name="vNames">
  <xsl:for-each select="/*/choices/*">
   <xsl:value-of select="concat(' ', name(), ' ')"/>
  </xsl:for-each>
 </xsl:variable>

 <xsl:template match="/">
  <xsl:copy-of select=
  "/*/choice/*
         [contains($vNames, concat(' ', name(), ' '))]
           [1]"/>
 </xsl:template>
</xsl:stylesheet>
红色

III.使用按键

(*/choice/*[some $c in ../../choices/* satisfies name($c)=name()])[1]
<t>
    <choices>
        <sic  />
        <corr />
        <reg  />
        <orig />
    </choices>
    <choice>
        <corr>Red</corr>
        <sic>Blue</sic>
    </choice>
</t>
<corr>Red</corr>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:key name="kChoiceByName" match="choice/*"
   use="boolean(/*/choices/*[name()=name(current())])"/>

 <xsl:template match="/">
  <xsl:copy-of select="/*/choice/*[key('kChoiceByName', true())][1]"/>
 </xsl:template>
</xsl:stylesheet>

当对相同的XML文档(如上)应用此转换时,会产生相同的正确结果

(*/choice/*[some $c in ../../choices/* satisfies name($c)=name()])[1]
<t>
    <choices>
        <sic  />
        <corr />
        <reg  />
        <orig />
    </choices>
    <choice>
        <corr>Red</corr>
        <sic>Blue</sic>
    </choice>
</t>
<corr>Red</corr>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

  <xsl:key name="kChoiceByName" match="choice/*"
   use="boolean(/*/choices/*[name()=name(current())])"/>

 <xsl:template match="/">
  <xsl:copy-of select="/*/choice/*[key('kChoiceByName', true())][1]"/>
 </xsl:template>
</xsl:stylesheet>
红色

建议读者尝试理解这一切是如何“起作用的”:

文档不是“应用”到样式上的,而是相反的。III真的起作用吗?键的值可以是在调用key()之前不会计算的表达式?那么当调用key()时,current()是上下文吗?如果select将针对多个实例运行,那么Sean创建静态键值的速度似乎要快得多还是这位读者看不到“这一切是如何运作的”@JPM,是的,它是如何运作的!是的,在调用
key()
函数之前没有理由构造索引。这是理解
xsl:key
key()
函数如何工作的一个很好的测试。效率:索引应该花费相同的时间。仅获取键值的第一项也应该是O(1)。如果优化器很好,它甚至不会构造整个索引,而只是
true()
的第一个值。要验证这个“真的有效”,请尝试将不同的
choice/*
元素作为其父元素的第一个子元素——您将看到解决方案在所有情况下都有效。这是一个思维拉伸器。谢谢但是,除非这显然比肖恩的快,否则我想我通常会采用他的方法,因为它只依赖于按惯例记录的密钥使用,因此以后会更容易维护。但是非常有趣!谢谢。@JPM,它是否更快取决于使用了哪个XSLT处理器(优化器部分),而且只有在索引非常长的情况下,速度才重要。因此,要比较性能,需要改变两件事——XSLT处理器和
choices/*
choices/*
的数量。我希望如果有足够多的
choices/*
choice/*
以及一个好的优化器,我的解决方案可能会更快——因为只需要构建索引的第一项。@JPM,不管效率如何(我的第一次测试显示两个解决方案的效率大致相同),我更喜欢较短的解决方案。此外,如果每次执行只执行一次搜索,那么如果无键解决方案的速度更快,也不会令人惊讶。是否可以假设存在一个
choice
元素?或者可能有多个?它们可能都没有吗?
choices
choice
都不会有多个同名元素。现在,其中一个或两个都可以是空的,但如果这样做给了我一个更干净的解决方案,我可以不允许。你误解了我的问题。这不是关于
选择的孩子的基数,而是关于
选择的基数。例如,
计数(/t/choice)=2是否可能?哦,对不起。是的,
choice
将多次出现,分散在整个层次结构中<代码>
只显示一次,作为一个配置参数,指示如何处理
的所有实例。这很好。即使存在多个
选项
元素,我的解决方案仍然正确。