如何在xslt中设置每个节点的增量

时间:2012-08-21 21:43:19

标签: xslt

我有这个xml:

<root>
    <row>
        <number>1001461</number>
        <unit>CAN</unit>
    </row>
    <row>
        <number>1001462</number>
        <unit>KG</unit>
    </row>
</root>

我的Xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>
    <xsl:output method="xml" indent="yes"/>
    <xsl:param name="formid" select="60202" />


  <xsl:template match="@* | node()">
      <DocumentElement>
          <xsl:apply-templates>
            <xsl:with-param name="primarykey" select="position()"/>
          </xsl:apply-templates>
      </DocumentElement>
    </xsl:template>

  <xsl:template match="row" name="trow">
    <xsl:param name="primarykey"/>
    <xsl:for-each select="*">
      <SaveDataTable>
        <KeyName>
          <xsl:value-of select="name()"/>
        </KeyName>
        <KeyValue>
          <xsl:value-of select="."/>
        </KeyValue>
        <PrimaryKey>
          <xsl:value-of select="concat('-',$primarykey)"/>
        </PrimaryKey>
        <FormId>
          <xsl:value-of select="$formid"/>
        </FormId>
      </SaveDataTable>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

预期输出:(注意前两个<PrimaryKey>有-1,接下来两个有-2,这就是我的需要)

<DocumentElement>
    <SaveDataTable>
        <KeyName>number</KeyName>
        <KeyValue>1001461</KeyValue>
        <PrimaryKey>-1</PrimaryKey>
        <FormId>60202</FormId>
    </SaveDataTable>
    <SaveDataTable>
        <KeyName>unit</KeyName>
        <KeyValue>CAN</KeyValue>
        <PrimaryKey>-1</PrimaryKey>
        <FormId>60202</FormId>
    </SaveDataTable>
    <SaveDataTable>
        <KeyName>number</KeyName>
        <KeyValue>1001462</KeyValue>
        <PrimaryKey>-2</PrimaryKey>
        <FormId>60202</FormId>
    </SaveDataTable>
    <SaveDataTable>
        <KeyName>unit</KeyName>
        <KeyValue>KG</KeyValue>
        <PrimaryKey>-2</PrimaryKey>
        <FormId>60202</FormId>
    </SaveDataTable>
</DocumentElement>

基本上每<row>...</row><PrimaryKey>-1</PrimaryKey>应减1,但它没有发生。所有<PrimaryKey>元素的值都为-1而不是-1,-2等等。

===========================================

更新: 我有点工作,但我不确定它是否有效。

使用xslt(可能需要改进):

<xsl:stylesheet version="1.0" exclude-result-prefixes="msxsl" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
    <xsl:output method="xml" indent="yes"/>
    <xsl:param name="formid" select="60202"/>
    <xsl:template match="@* | node()">
        <DocumentElement>
            <xsl:for-each select="row">
                <xsl:call-template name="trow">
                    <xsl:with-param name="primarykey" select="position()"/>
                </xsl:call-template>
            </xsl:for-each>
        </DocumentElement>
    </xsl:template>
    <xsl:template name="trow">
        <xsl:param name="primarykey"/>
        <xsl:for-each select="*">
            <SaveDataTable>
                <KeyName>
                    <xsl:value-of select="name()"/>
                </KeyName>
                <KeyValue>
                    <xsl:value-of select="."/>
                </KeyValue>
                <PrimaryKey>
                    <xsl:value-of select="concat('-',$primarykey)"/>
                </PrimaryKey>
                <FormId>
                    <xsl:value-of select="$formid"/>
                </FormId>
            </SaveDataTable>
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

3 个答案:

答案 0 :(得分:2)

另一种方法(以'推'而不是'拉'式)会将处理分解为模板:

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

    <xsl:output method="xml" indent="yes"/>
    <xsl:param name="formid" select="60202"/>

DocumentElement

中包装整个文档的结果
    <xsl:template match="/">
        <DocumentElement>
          <xsl:apply-templates/>
        </DocumentElement>
    </xsl:template>

对于每一行,获取其位置编号。我们使用xsl:number而不是position(),因为我们不想计算文本节点。

    <xsl:template match="row" priority="10">
      <xsl:variable name="pos">
        <xsl:number count="row" level="single"/>
      </xsl:variable>
      <SaveDataTable>
        <xsl:apply-templates>
          <xsl:with-param name="pkey" select="-1 * $pos"/>
        </xsl:apply-templates>
      </SaveDataTable>
    </xsl:template>

row元素的每个子元素上,发出包含键名,键值,主键和表单ID的SaveDataTable元素。

    <xsl:template match="row/*">
      <xsl:param name="pkey"/>
      <KeyName>
        <xsl:value-of select="name()"/>
      </KeyName>
      <KeyValue>
        <xsl:value-of select="."/>
      </KeyValue>
      <PrimaryKey>
        <xsl:value-of select="$pkey"/>
      </PrimaryKey>
      <FormId>
        <xsl:value-of select="$formid"/>
      </FormId>
    </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

你可以尝试这个解决方案,但我认为它效率低于你的解决方案:

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

  <xsl:param name="formid" select="60202"/>

  <xsl:template match="/root">
    <DocumentElement>
      <xsl:apply-templates select="row/*"/>
    </DocumentElement>
  </xsl:template>

  <xsl:template match="*">
    <SaveDataTable>
      <KeyName>
        <xsl:value-of select="name()"/>
      </KeyName>
      <KeyValue>
        <xsl:value-of select="."/>
      </KeyValue>
      <PrimaryKey>
        <xsl:value-of select="-1 * (count(../preceding-sibling::row) + 1)"/>
      </PrimaryKey>
      <FormId>
        <xsl:value-of select="$formid"/>
      </FormId>
    </SaveDataTable>
  </xsl:template>
</xsl:stylesheet>

答案 2 :(得分:0)

推送样式解决方案 - 类似于C. M. Sperberg-McQueen,但可能略高一些,因为没有计算xsl:number并且位置作为参数传递。

另一个不同之处在于我们不需要在任何模板上指定priority属性。

另外,我们不要乘以-1。

<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:param name="pFormid" select="60202"/>

        <xsl:template match="/*">
            <DocumentElement>
                <xsl:apply-templates/>
            </DocumentElement>
        </xsl:template>

        <xsl:template match="row">
            <xsl:apply-templates select="*">
             <xsl:with-param name="pPos" select="position()"/>
            </xsl:apply-templates>
        </xsl:template>

        <xsl:template match="row/*">
          <xsl:param name="pPos"/>

            <SaveDataTable>
                    <KeyName>
                        <xsl:value-of select="name()"/>
                    </KeyName>
                    <KeyValue>
                        <xsl:value-of select="."/>
                    </KeyValue>
                    <PrimaryKey>
                        <xsl:value-of select="-$pPos"/>
                    </PrimaryKey>
                    <FormId>
                        <xsl:value-of select="$pFormid"/>
                    </FormId>
                </SaveDataTable>
        </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时

<root>
    <row>
        <number>1001461</number>
        <unit>CAN</unit>
    </row>
    <row>
        <number>1001462</number>
        <unit>KG</unit>
    </row>
</root>

产生了想要的正确结果

<DocumentElement>
   <SaveDataTable>
      <KeyName>number</KeyName>
      <KeyValue>1001461</KeyValue>
      <PrimaryKey>-1</PrimaryKey>
      <FormId>60202</FormId>
   </SaveDataTable>
   <SaveDataTable>
      <KeyName>unit</KeyName>
      <KeyValue>CAN</KeyValue>
      <PrimaryKey>-1</PrimaryKey>
      <FormId>60202</FormId>
   </SaveDataTable>
   <SaveDataTable>
      <KeyName>number</KeyName>
      <KeyValue>1001462</KeyValue>
      <PrimaryKey>-2</PrimaryKey>
      <FormId>60202</FormId>
   </SaveDataTable>
   <SaveDataTable>
      <KeyName>unit</KeyName>
      <KeyValue>KG</KeyValue>
      <PrimaryKey>-2</PrimaryKey>
      <FormId>60202</FormId>
   </SaveDataTable>
</DocumentElement>