如何重置xslt 1.0中的位置(position())

时间:2014-02-12 11:52:37

标签: xslt xpath xslt-1.0

我有一个XML文件,我有重复,他们有自己的ITEM_ID和NAME。正如您在示例中所看到的,我们有6个ITEM:

<ITEMS>
    <ITEM>
        <ITEM_ID>1234</ITEM_ID>
        <ITEM_NAME>TEST_ITEM_1</ITEM_NAME>
    </ITEM>
    <ITEM>
        <ITEM_ID>3216</ITEM_ID>
        <ITEM_NAME>TEST_ITEM_2</ITEM_NAME>
    </ITEM>
    <ITEM>
        <ITEM_ID>8956</ITEM_ID>
        <ITEM_NAME>TEST_ITEM_3</ITEM_NAME>
    </ITEM>
    <ITEM>
        <ITEM_ID>4562</ITEM_ID>
        <ITEM_NAME>TEST_ITEM_4</ITEM_NAME>
    </ITEM>
    <ITEM>
        <ITEM_ID>4562</ITEM_ID>
        <ITEM_NAME>TEST_ITEM_5</ITEM_NAME>
    </ITEM>
    <ITEM>
        <ITEM_ID>8569</ITEM_ID>
        <ITEM_NAME>TEST_ITEM_6</ITEM_NAME>
    </ITEM>
</ITEMS>

我希望结果如下:

<ARTICLES>
    <ARTICLE CODE="1">
        <ARTICLE_ID>1234</ARTICLE_ID>
        <ARTICLE_NAME>TEST_ARTICLE_1</ARTICLE_NAME>
    </ARTICLE>
    <ARTICLE CODE="2">
        <ARTICLE_ID>3216</ARTICLE_ID>
        <ARTICLE_NAME>TEST_ARTICLE_2</ARTICLE_NAME>
    </ARTICLE>
    <ARTICLE CODE="3">
        <ARTICLE_ID>8956</ARTICLE_ID>
        <ARTICLE_NAME>TEST_ARTICLE_3</ARTICLE_NAME>
    </ARTICLE>
    <ARTICLE CODE="4">
        <ARTICLE_ID>4562</ARTICLE_ID>
        <ARTICLE_NAME>TEST_ARTICLE_4</ARTICLE_NAME>
    </ARTICLE>
    <ARTICLE CODE="4">
        <ARTICLE_ID>4562</ARTICLE_ID>
        <ARTICLE_NAME>TEST_ARTICLE_5</ARTICLE_NAME>
    </ARTICLE>
    <ARTICLE CODE="5">
        <ARTICLE_ID>8569</ARTICLE_ID>
        <ARTICLE_NAME>TEST_ARTICLE_6</ARTICLE_NAME>
    </ARTICLE>
</ARTICLES>

这里,属性CODE应该具有ITEM的位置,但是ITEM_ID相同,例如第4和第5,那么在结果文件中,CODE应该具有与结果文件中相同的值(CODE)属性)。下一个节点不应该具有输入xml中的实际位置,但增量编号应为“5”,因为您可以看到结果XML中的最后一个ARTICLE。

提前致谢。

1 个答案:

答案 0 :(得分:1)

您将获得编号

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output indent="yes"/>

<xsl:key name="by-id" match="ITEM" use="ITEM_ID"/>

<xsl:template match="ITEMS">
  <ARTICLES>
    <xsl:apply-templates select="ITEM[generate-id() = generate-id(key('by-id', ITEM_ID)[1])]"/>
  </ARTICLES>
</xsl:template>

<xsl:template match="ITEM">
  <xsl:variable name="pos" select="position()"/>
  <xsl:apply-templates select="key('by-id', ITEM_ID)" mode="article">
    <xsl:with-param name="code" select="$pos"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="ITEM" mode="article">
  <xsl:param name="code"/>
  <ARTICLE CODE="{$code}">
    <xsl:apply-templates/>
  </ARTICLE>
</xsl:template>

<xsl:template match="ITEM_ID">
  <ARTICLE_ID>
    <xsl:apply-templates/>
  </ARTICLE_ID>
</xsl:template>

<xsl:template match="ITEM_NAME">
  <ARTICLE_NAME>
    <xsl:apply-templates/>
  </ARTICLE_NAME>
</xsl:template>

</xsl:stylesheet>

您似乎还希望将每个名称中的“ITEM”替换为“ARTICLE”,这可以通过ITEM_NAME模板中调用的模板来完成。这是一个例子:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output indent="yes"/>

<xsl:key name="by-id" match="ITEM" use="ITEM_ID"/>

<xsl:template match="ITEMS">
  <ARTICLES>
    <xsl:apply-templates select="ITEM[generate-id() = generate-id(key('by-id', ITEM_ID)[1])]"/>
  </ARTICLES>
</xsl:template>

<xsl:template match="ITEM">
  <xsl:variable name="pos" select="position()"/>
  <xsl:apply-templates select="key('by-id', ITEM_ID)" mode="article">
    <xsl:with-param name="code" select="$pos"/>
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="ITEM" mode="article">
  <xsl:param name="code"/>
  <ARTICLE CODE="{$code}">
    <xsl:apply-templates/>
  </ARTICLE>
</xsl:template>

<xsl:template match="ITEM_ID">
  <ARTICLE_ID>
    <xsl:apply-templates/>
  </ARTICLE_ID>
</xsl:template>

<xsl:template match="ITEM_NAME">
  <ARTICLE_NAME>
    <xsl:call-template name="replace">
      <xsl:with-param name="input" select="."/>
      <xsl:with-param name="to-be-replaced" select="'ITEM'"/>
      <xsl:with-param name="replacement" select="'ARTICLE'"/>
    </xsl:call-template>
  </ARTICLE_NAME>
</xsl:template>

<xsl:template name="replace">
  <xsl:param name="input"/>
  <xsl:param name="to-be-replaced"/>
  <xsl:param name="replacement"/>
  <xsl:choose>
    <xsl:when test="not(contains($input, $to-be-replaced))">
      <xsl:value-of select="$input"/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="substring-before($input, $to-be-replaced)"/>
      <xsl:copy-of select="$replacement"/>
      <xsl:call-template name="replace">
        <xsl:with-param name="input" select="substring-after($input, $to-be-replaced)"/>
        <xsl:with-param name="to-be-replaced" select="$to-be-replaced"/>
        <xsl:with-param name="replacement" select="$replacement"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

</xsl:stylesheet>