Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.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
Java 为什么可以';我是否在XPath表达式中使用exsl:node set/set:distinct来检索节点的值?_Java_Xslt_Xpath_Xerces_Xalan - Fatal编程技术网

Java 为什么可以';我是否在XPath表达式中使用exsl:node set/set:distinct来检索节点的值?

Java 为什么可以';我是否在XPath表达式中使用exsl:node set/set:distinct来检索节点的值?,java,xslt,xpath,xerces,xalan,Java,Xslt,Xpath,Xerces,Xalan,在xslt样式表中,我使用方法exsl:node set和set:distinct从包含结果树片段的变量中访问和筛选唯一节点。 我可以将这些节点的值写入输出文件,例如: <xsl:variable name="myNodes"> <xsl:call-template name="getNodes"/> </xsl:variable> <xsl:for-each select="set:distinct(exsl:node-set($myNodes)

在xslt样式表中,我使用方法
exsl:node set
set:distinct
从包含结果树片段的变量中访问和筛选唯一节点。 我可以将这些节点的值写入输出文件,例如:

<xsl:variable name="myNodes">
  <xsl:call-template name="getNodes"/>
</xsl:variable>

<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
  <xsl:value-of select="."/>
</xsl:for-each>

正如预期的那样,键的值将写入输出中。 但是,如果尝试在XPath表达式中使用值,则会失败:

<xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
  <xsl:variable name="result" select="/tree//somenode[@key = current()]"/>
  <xsl:value-of select="$result"/>
</xsl:for-each>

现在,输出是空的,而我知道输入xml中有一个“somenode”,应该由XPath表达式选择,它的值不是空的

现在我的问题是:为什么会发生这种情况

我使用的是Java1.6、Xerce2.7和Xalan2.7

更新: 根据要求,示例的一些数据如下: xml文档包含:

<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>

123
0815
getNodes模板:

<xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
</xsl:template>

这里有一个转换,它可以实现与您想要的接近的功能

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:set="http://exslt.org/sets"
 xmlns:exsl="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xsl:variable name="myNodes">
    <xsl:call-template name="getNodes"/>
  </xsl:variable>


  <xsl:variable name="vDoc" select="/"/>

  <xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
    <xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
    <xsl:copy-of select="$result"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>
<somenode key="123"/>

应用于提供的XML文档时

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:set="http://exslt.org/sets"
 xmlns:exsl="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xsl:variable name="myNodes">
    <xsl:call-template name="getNodes"/>
  </xsl:variable>


  <xsl:variable name="vDoc" select="/"/>

  <xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
    <xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
    <xsl:copy-of select="$result"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>
<somenode key="123"/>

123
0815
产生所需结果

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:set="http://exslt.org/sets"
 xmlns:exsl="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xsl:variable name="myNodes">
    <xsl:call-template name="getNodes"/>
  </xsl:variable>


  <xsl:variable name="vDoc" select="/"/>

  <xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
    <xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
    <xsl:copy-of select="$result"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>
<somenode key="123"/>

注意事项

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:set="http://exslt.org/sets"
 xmlns:exsl="http://exslt.org/common"
 >
 <xsl:output omit-xml-declaration="yes"/>

 <xsl:template match="/">
  <xsl:variable name="myNodes">
    <xsl:call-template name="getNodes"/>
  </xsl:variable>


  <xsl:variable name="vDoc" select="/"/>

  <xsl:for-each select="set:distinct(exsl:node-set($myNodes)/key)">
    <xsl:variable name="result" select="$vDoc/tree//somenode[@key = current()]"/>
    <xsl:copy-of select="$result"/>
  </xsl:for-each>
 </xsl:template>

 <xsl:template name="getNodes">
  <xsl:for-each select="/tree/num">
    <xsl:element name="key">
      <xsl:value-of select="."/>
    </xsl:element>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>
<tree>
  <somenode key="123"/>
  <num>123</num>
  <num>0815</num>
</tree>
<somenode key="123"/>
  • 无法直接在
    中访问源XML文档,因为此指令将当前节点设置为另一文档中的节点,即由
    exsl:node-set()创建的临时树

  • 因此,我们在变量
    $vDoc
    中捕获源XML文档,然后通过此变量访问
    中的源XML文档

  • 元素
    没有文本节点的后代,因此没有字符串值。对其使用
    将不会产生任何输出。这就是为什么我们在这里使用
    ——它复制完整的元素,然后我们看到结果


  • 此样式表与您想要的样式表相同,无需扩展:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:key name="NumByValue" match="num" use="."/>
        <xsl:template match="num[count(.|key('NumByValue',.)[1])=1]">
            <xsl:copy-of select="../somenode[@key=current()]"/>
        </xsl:template>
    </xsl:stylesheet>
    
    
    
    输出:

    <somenode key="123" />
    
    
    
    您能为我们提供一些示例数据吗?好问题(+1)。请参阅我的答案,了解代码中问题的解决方案和解释。谢谢!我以为表达式“/”总是允许我访问xml文档的根节点,但不知道使用临时树可以改变这种行为。@xor\U eq:
    /
    正在选择当前文档的根节点。当前文档由
    创建为临时树,因此
    /
    正在选择临时树的根节点。看起来有点像过滤唯一元素的muenchian方法。但我这里的问题是(这就是为什么我要使用扩展方法)我必须计算节点,然后从中提取节点。正因为如此,我不能使用xsl:key,因为这是一个顶级元素。@xor_eq:我在颠倒你的逻辑。不是用所有的
    num
    元素转换成
    key
    元素来构建一个RTF,然后将这个RTF转换成一个节点集,对那些具有唯一字符串值的元素进行迭代,最后用这样的
    @key
    输出所有
    somenode
    元素。因为源代码中有唯一的值,所以不需要两步过程。为了提高性能(避免节点集比较),您可以使用另一个键匹配
    somenode
    元素,并使用
    @key
    @Alejandro:您完全正确,但是,在这个问题中,我编写了一个非常简单的示例。正如我现在看到的,这个例子也很糟糕,因为我没有明确说明那些
    num
    值不必是唯一的。在我的原始代码中,我的源代码中没有唯一的值,这更像是我已经将每个
    num
    元素提取了几百次,所以我必须首先提取唯一的值。@xor\U eq:您写道:我已经将每个num元素提取了几百次,所以我必须首先提取唯一的值。对这就是我按值对
    num
    进行分组的原因。@Alejandro:是的,但是在xsl:key的帮助下。我不能使用这个元素,因为那些
    num
    元素不在源代码中(这只是我的示例中的情况),它们是计算出来的。我不妨先创建另一个xml文档,它在需要之前计算所有
    num
    元素,然后使用xsl:key进行分组,依此类推。。。但那样我就不会问了。我宁愿不必创建另一个xml文档,也不必动态计算所需的值。这使得我需要使用ext.函数,因为递归版本(我也尝试过)会在一定的复杂度下消亡