【问题标题】:Compare variable in preceding-sibling with current node将前同级中的变量与当前节点进行比较
【发布时间】:2012-12-07 14:31:24
【问题描述】:

我有以下模板:

<xsl:template match="footnote">
    <xsl:variable name = "string">
        <xsl:value-of select="."/>
    </xsl:variable>
    <xsl:variable name = "bool">
        <xsl:if test="$string = preceding-sibling::node()/$string">
            <xsl:text>false</xsl:test>
        </xsl:if>
    </xsl:variable>
    <xsl:if test="$bool != 'false'">
        <!-- DO STUFF -->
    </xsl:if>
</xsl:template>

我正在尝试检查当前节点的 $string 变量,并对照所有以前的脚注节点检查它们是否具有相同的 $string 变量。如果它与前面的任何兄弟不匹配,那么它应该做一些事情,否则它什么也不做。

使用我的代码,测试“$string =previous-sibling::node()/$string”总是评估为真,即使尚未创建脚注节点。

谁能帮帮我?我很难创建表达式来与之前所有兄弟姐妹中的变量进行比较。

编辑:示例 XML:

<xml>
<footnote>Footnote 1</footnote>
<footnote>Footnote 2</footnote>
<footnote>Footnote 1</footnote>
<footnote>Footnote 1</footnote>
<footnore>Footnote 3</footenote>
</xml>

我正在尝试将其转换为:

<xml>
<footnote>Footnote 1</footnote>
<footnote>Footnote 2</footnote>
<footnote>Footnore 3</footnore>
</xml

【问题讨论】:

  • 你能添加到 queestion xml 中,这个 xslt 将被应用吗?
  • 这种情况下不需要定义变量!请检查我的答案,只有模板覆盖才能消除重复的节点(值)..

标签: xslt


【解决方案1】:

嗯。发布您的输出 XML 使其更加清晰!解决方案就到这里了:

示例 XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
  <footnote>Matching</footnote>
  <footnote>Example1</footnote>
  <footnote>Matching</footnote>
  <footnote>Example2</footnote>
  <footnote>Example3</footnote>
</root>

XSL:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
  <xsl:template match="footnote[.=preceding-sibling::footnote/.]"/>
</xsl:stylesheet>

结果:

<?xml version="1.0" encoding="utf-8"?>
<xml>
  <footnote>Matching</footnote>
  <footnote>Example1</footnote>
  <footnote>Example2</footnote>
  <footnote>Example3</footnote>
</xml>

【讨论】:

  • 试过了,结果总是假的。
  • 请立即尝试!有一点点误会..现在它符合你的要求
【解决方案2】:

假设您想检查当前脚注text() 与先前脚注text()'s 的值的唯一性,那么您只需检查preceding-sibling::node()'s text():

<xsl:if test="$string = preceding-sibling::node()/text()">

例如

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0"
                >
    <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" indent="yes" />

    <xsl:template match="/xml">
        <xml>
            <xsl:apply-templates select="footnote" />
        </xml>
    </xsl:template>

    <xsl:template match="footnote">
        <xsl:variable name = "string">
            <xsl:value-of select="./text()"/>
        </xsl:variable>
        <xsl:variable name = "bool">
            <xsl:if test="$string = preceding-sibling::node()/text()">
                <xsl:text>false</xsl:text>
            </xsl:if>
        </xsl:variable>
        <xsl:if test="$bool != 'false'">
            <xsl:copy-of select="."></xsl:copy-of>
        </xsl:if>
    </xsl:template>

</xsl:stylesheet>

会转输入:

<xml>
    <footnote>
        someVal
    </footnote>
    <footnote>
        anotherVal
    </footnote>
    <footnote>
        anotherVal
    </footnote>
    <footnote>
        newVal
    </footnote>
</xml>

进入:

<xml>
  <footnote>
        someVal
    </footnote>
  <footnote>
        anotherVal
    </footnote>
  <footnote>
        newVal
    </footnote>
</xml>

如果您的意图是识别元素中的组,您还应该查看 Muenchian 分组。

【讨论】:

    【解决方案3】:

    你可以使用

    <xsl:template match="footnote[not(. = preceding-sibling::footnote)]">
    

    创建仅在给定脚注字符串的第一个实例时触发的模板。 . = preceding-sibling::footnote 如果此节点的字符串值与其前面的兄弟节点的 any 的字符串值相同,则为 true,因此如果与 all 不同,not(....) 将为 true他们中的一个。

    但是对于大型文档,这将是相当低效的(脚注元素的数量呈二次方)。最好使用 &lt;xsl:for-each-group&gt; (XSLT 2.0) 或 Muenchian Grouping (XSLT 1.0) 将 footnote 元素按其字符串值分组,并从每个组中提取第一个元素。

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:key name="fn" match="footnote" use="." />
    
      <!-- Ignore all but the first footnote for a given value -->
      <xsl:template match="footnote[generate-id() != generate-id(key('fn', .)[1])]" />
    
      <!-- copy everything else verbatim -->
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
    </xsl:stylesheet>
    

    【讨论】:

      【解决方案4】:

      <xsl:template match="footnote">
      
          <xsl:variable name = "string">
            <xsl:value-of select="./text()"/>
          </xsl:variable>
          <xsl:variable name = "bool">
            <xsl:if test="$string != preceding-sibling::node()/text()">
              <xsl:text>false</xsl:text>
          </xsl:if>
          </xsl:variable>
          <xsl:if test="$bool != 'false'">
              true
          </xsl:if>
        <xsl:if test="$bool = 'false'">
          false
        </xsl:if>
        </xsl:template>
      

      【讨论】:

        【解决方案5】:

        在 XSLT 2.0 中,您有一个 distinct-values 函数:

        <xsl:for-each select="distinct-values(footnote)">
            <footnote><xsl:value-of select="."/></footnote>
        </xsl:for-each>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多