如何将多个XML组合成单个XSLT转换?

时间:2013-04-23 03:03:33

标签: xml xslt

我有一个输入xml,我必须在其中对元素进行分组,转换Currency格式并删除命名空间以添加新的命名空间。 我为每个提到的操作创建了3个XSLT程序,如果通过输入第一个到第二个XSLT的输出,一个接一个地执行,最终结果很好。 但是,我想将所有XSLT模板组合到单个XSLT转换文档中。 合并后,我没有得到所需的输出xml,而是每个节点都添加了命名空间,并且分组失控而不格式化货币格式。 示例XML是:

<?xml version="1.0" encoding="UTF-8"?>
<ns1:Root_Users xmlns:ns1="http://test.com/Users">
   <Users>
      <Id>111</Id>
      <Name>aaa</Name>
      <Division>HR</Division>
      <Salary>1000</Salary>
   </Users>
   <Users>
      <Id>222</Id>
      <Name>bbb</Name>
      <Division>FD</Division>
      <Salary>2000</Salary>
   </Users>
   <Users>
      <Id>333</Id>
      <Name>ccc</Name>
      <Division>HR</Division>
      <Salary>3000</Salary>
   </Users>
   <Users>
      <Id>444</Id>
      <Name>ddd</Name>
      <Division>FD</Division>
      <Salary>4000</Salary>
   </Users>
   <Users>
      <Id>555</Id>
      <Name>eee</Name>
      <Division>IT</Division>
      <Salary>5000</Salary>
   </Users>
</ns1:Root_Users>

我使用了以下XSLT转换来实现输出。

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

  <!-- Grouping the Users for each Division -->
  <xsl:key name="GroupKey" match="Users" use="Division"/>
  <xsl:template match="/*">
        <Root_Users>
            <xsl:apply-templates/>
        </Root_Users>
  </xsl:template>
  <xsl:template match="Users[generate-id()=generate-id(key('GroupKey',Division)[1])]">
        <Department name="{Division}">
            <xsl:copy-of select="key('GroupKey',Division)"/>
        </Department>
  </xsl:template>
  <xsl:template match="Users[not(generate-id()=generate-id(key('GroupKey',Division)[1]))]"/>

  <!-- Converting Salary to Denmark Currency Format -->
  <xsl:decimal-format name="DenmarkCurrencyFormat" grouping-separator="." decimal-separator=","/>
  <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
  </xsl:template>
  <xsl:template match="//Salary">
        <xsl:copy>
            <xsl:value-of select="format-number(., 'kr ###.###.###,00', 'DenmarkCurrencyFormat')"/>
        </xsl:copy>
  </xsl:template>


  <!-- Removing and Adding new Namespace to Root -->  
  <xsl:template match="/*">
    <xsl:element name="{local-name()}" namespace="http://test.com/Department">
            <xsl:apply-templates select="@* | node()" />
        </xsl:element>
  </xsl:template>
  <xsl:template match="@*">
        <xsl:attribute name="{local-name()}">
            <xsl:value-of select="." />
        </xsl:attribute>
  </xsl:template>
  <xsl:template match="text() | comment() | processing-instruction()">
        <xsl:copy />
  </xsl:template>

</xsl:stylesheet>

当应用于输入xml时,我得到以下输出xml:

<Root_Users xmlns="http://test.com/Department">
    <Department xmlns="" name="HR">
        <Users xmlns:ns1="http://test.com/Users">
            <Id>111</Id>
            <Name>aaa</Name>
            <Division>HR</Division>
            <Salary>1000</Salary>
        </Users>
        <Users xmlns:ns1="http://test.com/Users">
            <Id>333</Id>
            <Name>ccc</Name>
            <Division>HR</Division>
            <Salary>3000</Salary>
        </Users>
    </Department>
    <Department xmlns="" name="FD">
        <Users xmlns:ns1="http://test.com/Users">
            <Id>222</Id>
            <Name>bbb</Name>
            <Division>FD</Division>
            <Salary>2000</Salary>
        </Users>
        <Users xmlns:ns1="http://test.com/Users">
            <Id>444</Id>
            <Name>ddd</Name>
            <Division>FD</Division>
            <Salary>4000</Salary>
        </Users>
    </Department>
    <Department xmlns="" name="IT">
        <Users xmlns:ns1="http://test.com/Users">
            <Id>555</Id>
            <Name>eee</Name>
            <Division>IT</Division>
            <Salary>5000</Salary>
        </Users>
    </Department>
</Root_Users>

但是所需的输出如下所述。

<Root_Users xmlns="http://test.com/Department">
    <Department name="HR">
        <Users>
            <Id>111</Id>
            <Name>aaa</Name>
            <Division>HR</Division>
            <Salary>kr 1.000,00</Salary>
        </Users>
        <Users>
            <Id>333</Id>
            <Name>ccc</Name>
            <Division>HR</Division>
            <Salary>kr 3.000,00</Salary>
        </Users>
    </Department>
    <Department name="FD">
        <Users>
            <Id>222</Id>
            <Name>bbb</Name>
            <Division>FD</Division>
            <Salary>kr 2.000,00</Salary>
        </Users>
        <Users>
            <Id>444</Id>
            <Name>ddd</Name>
            <Division>FD</Division>
            <Salary>kr 4.000,00</Salary>
        </Users>
    </Department>
    <Department name="IT">
        <Users>
            <Id>555</Id>
            <Name>eee</Name>
            <Division>IT</Division>
            <Salary>kr 5.000,00</Salary>
        </Users>
    </Department>
</Root_Users>

请帮助我获得所需的xml。我非常接近,但无法找到究竟导致问题的原因。 非常感谢你的指点。

1 个答案:

答案 0 :(得分:1)

你的解决方案走在正确的轨道上 - 我注意到的两件主要事情:

  1. 我通过下面的解决方案中的倒数第二个模板解决了无关名称空间的问题;还有其他方法可以做到,但这就是我今晚的大脑。 :)
  2. 请注意,<xsl:decimal-format>指令必须位于顶层。
  3. 当这个XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns="http://test.com/Department" 
      version="1.0">
      <xsl:output omit-xml-declaration="yes" indent="yes"/>
      <xsl:strip-space elements="*"/>
    
      <xsl:decimal-format
        name="DenmarkCurrencyFormat"
        grouping-separator="."
        decimal-separator=","/>
    
      <xsl:key
        name="kUserByDivision"
        match="Users"
        use="Division"/>
    
      <xsl:template match="@*|node()">
        <xsl:copy>
          <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:template match="/*">
        <Root_Users>
          <xsl:apply-templates
            select="*[generate-id() = 
                      generate-id(key('kUserByDivision', Division)[1])]"/>
        </Root_Users>
      </xsl:template>
    
      <xsl:template match="Users">
        <Department name="{Division}">
          <xsl:for-each select="key('kUserByDivision', Division)">
            <Users>
              <xsl:apply-templates/>
            </Users>
          </xsl:for-each>
        </Department>
      </xsl:template>
    
      <xsl:template match="Users/*">
        <xsl:element name="{name()}">
          <xsl:apply-templates/>
        </xsl:element>
      </xsl:template>
    
      <xsl:template match="Salary/text()">
        <xsl:value-of
          select="concat('kr ',
                         format-number(.,
                                       '###.###,00',
                                       'DenmarkCurrencyFormat'))"/>
      </xsl:template>
    </xsl:stylesheet>
    

    ...适用于提供的XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <ns1:Root_Users xmlns:ns1="http://test.com/Users">
      <Users>
        <Id>111</Id>
        <Name>aaa</Name>
        <Division>HR</Division>
        <Salary>1000</Salary>
      </Users>
      <Users>
        <Id>222</Id>
        <Name>bbb</Name>
        <Division>FD</Division>
        <Salary>2000</Salary>
      </Users>
      <Users>
        <Id>333</Id>
        <Name>ccc</Name>
        <Division>HR</Division>
        <Salary>3000</Salary>
      </Users>
      <Users>
        <Id>444</Id>
        <Name>ddd</Name>
        <Division>FD</Division>
        <Salary>4000</Salary>
      </Users>
      <Users>
        <Id>555</Id>
        <Name>eee</Name>
        <Division>IT</Division>
        <Salary>5000</Salary>
      </Users>
    </ns1:Root_Users>
    

    ...生成了想要的结果:

    <Root_Users xmlns="http://test.com/Department">
      <Department name="HR">
        <Users>
          <Id>111</Id>
          <Name>aaa</Name>
          <Division>HR</Division>
          <Salary>kr 1.000,00</Salary>
        </Users>
        <Users>
          <Id>333</Id>
          <Name>ccc</Name>
          <Division>HR</Division>
          <Salary>kr 3.000,00</Salary>
        </Users>
      </Department>
      <Department name="FD">
        <Users>
          <Id>222</Id>
          <Name>bbb</Name>
          <Division>FD</Division>
          <Salary>kr 2.000,00</Salary>
        </Users>
        <Users>
          <Id>444</Id>
          <Name>ddd</Name>
          <Division>FD</Division>
          <Salary>kr 4.000,00</Salary>
        </Users>
      </Department>
      <Department name="IT">
        <Users>
          <Id>555</Id>
          <Name>eee</Name>
          <Division>IT</Division>
          <Salary>kr 5.000,00</Salary>
        </Users>
      </Department>
    </Root_Users>