2

我有这个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>
4

3 回答 3

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元素上,发出一个SaveDataTable包含键名、键值、主键和表单 ID 的元素。

    <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>
于 2012-08-22T00:29:21.403 回答
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>
于 2012-08-21T22:41:00.423 回答
0

推式解决方案——类似于 CM Sperberg-McQueen 的解决方案,但由于xsl:number计算 no 并将位置作为参数传递,因此效率可能略高一些。

另一个区别是我们不需要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>
于 2012-08-22T05:01:39.583 回答