0

我有一个输入 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。我非常接近,但无法找到导致问题的确切原因。非常感谢您的指点。

4

1 回答 1

1

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

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

当这个 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>
于 2013-04-23T04:28:12.537 回答