首页 文章

XSL比较节点

提问于
浏览
1

您好我是xml的新手,想要使用xsl样式表比较一些值

`<a>
 <b>   <name>foo</name>   </b>
 <b>   <name>bar</name>   </b>
 <b>   <name>fred</name>  </b>
 <b>   <name>fred</name>  </b>
 </a>`

我想编写一个样式表来检查所有b节点并返回具有相同值的值,因此使用上面的简单示例我希望输出类似于:
"Your duplicate strings are fred"

我已经使用了一个for循环来返回所有值,但比较名称和返回重复项已经躲过我 . 如果可能,我想通过使用while类型循环来实现比较 .

感谢您的任何帮助 .

3 回答

  • 1

    一个基于_1447590的解决方案:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:key name="kName" match="b/name" use="text()" />
    
      <xsl:template match="/">
        <xsl:for-each select="//b/name">
          <xsl:if test="count(key('kName', text())) &gt; 1">
            <xsl:value-of select="concat('Your duplicate is: ', text(), '&#xA;')" />
          </xsl:if>
        </xsl:for-each>
      </xsl:template>
    </xsl:stylesheet>
    

    对于大型输入文档,这将比使用 preceding:: 检查的解决方案更有效 .

  • 2

    XSLT 1.0: A simple, solution using keys

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:output method="text"/>
     <xsl:key name="kNameByVal" match="name" use="."/>
    
     <xsl:template match="/*">
      Your duplicate strings are: <xsl:text/>
    
      <xsl:apply-templates select=
        "b/name[generate-id() = generate-id(key('kNameByVal', .)[2])]"/>
     </xsl:template>
    
     <xsl:template match="name">
      <xsl:if test="position() >1">, </xsl:if>
      <xsl:value-of select="."/>
     </xsl:template>
     <xsl:template match="text()"/>
    </xsl:stylesheet>
    

    II. XSLT 2.0 solution

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
     <xsl:variable name="vSeq" select="data(/a/b/name)"/>
    
     <xsl:template match="/">
      Your duplicate strings are: <xsl:text/>
      <xsl:sequence select="$vSeq[index-of($vSeq,.)[2]]"/>
     </xsl:template>
    </xsl:stylesheet>
    

    III. XPath 2.0 one-liner

    $vSeq[index-of($vSeq,.)[2]]
    

    这将生成给定序列中的所有值,这些值具有重复项(一组来自一组重复项) .

  • 1

    使用while循环是违反XSLT理念的,即使它可以完成 .

    有一些更容易的方法来做你想要的,例如:

    <?xml version="1.0" encoding="utf-8"?>
    <xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:output method='text' />
    <xsl:template match="b">
       <xsl:if test='preceding::b/name/text()=./name/text()'>
    Your duplicate is: <xsl:copy-of select='./name/text()' />
       </xsl:if>
    </xsl:template>
    
    </xsl:stylesheet>
    

    这是寻找节点b,并检查前面的b节点是否具有相同的名称文本

相关问题