【问题标题】:How to combine multiple XSL into single XSLT trasnformation?如何将多个 XML 组合成单个 XSLT 转换?
【发布时间】:2013-04-23 12:41:57
【问题描述】:

我有一个输入 xml,我必须在其中对元素进行分组、转换货币格式并删除命名空间以添加新的命名空间。 我为提到的每个操作创建了 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。我非常接近,但无法找到导致问题的确切原因。 非常感谢您的指点。

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    您的解决方案走上了正轨 - 我注意到了 2 件主要的事情:

    1. 我通过下面解决方案中的倒数第二个模板解决了无关名称空间的问题;还有其他方法可以做到这一点,但这就是今晚我想到的。 :)
    2. 请注意,&lt;xsl:decimal-format&gt; 指令需要位于顶层。

    当这个 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>
    

    【讨论】:

    • 完美!这就是我正在看的。 :) 非常感谢..所以在正确定义任何模板之前,我们需要先提及十进制格式和键.. 需要更改无关的命名空间并寻找使用模板添加命名空间而不是定义为流程指令。
    猜你喜欢
    • 2021-10-31
    • 2019-04-11
    • 2018-03-11
    • 2021-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-22
    • 2013-01-07
    相关资源
    最近更新 更多