XSLT-在每行上显示不同的节点数据(在所有行上显示第一个节点)

时间:2018-07-25 14:14:51

标签: xslt

我在所有节点上显示正确的信息时遇到问题。我刚得到所有节点中的第一个节点...

尝试了几种不同的方法,但是无法正确执行。我进入XSLT转换的第一周,所以慢慢到达那里:P

希望任何人都可以告诉我我在做什么错。预先谢谢你:)

编辑:我正在尝试根据NetMass划分GrossMass。

XML的一部分:

<?xml version="1.0" encoding="UTF-8"?>
<Job xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <Invoice>
    <TotGrossMass>1853.80</TotGrossMass>
    <TotNetMass>1752.00</TotNetMass>
    <InvoiceLine>
      <LineNo>1</LineNo>
      <GrossMass></GrossMass>
      <NetMass>212.3</NetMass>
    </InvoiceLine>
    <InvoiceLine>
      <LineNo>2</LineNo>
      <GrossMass></GrossMass>
      <NetMass>212.3</NetMass>
    </InvoiceLine>
    <InvoiceLine>
      <LineNo>3</LineNo>
      <GrossMass></GrossMass>
      <NetMass>227.4</NetMass>
    </InvoiceLine>
    <InvoiceLine>
      <LineNo>4</LineNo>
      <GrossMass></GrossMass>
      <NetMass>550</NetMass>
    </InvoiceLine>
    <InvoiceLine>
      <LineNo>5</LineNo>
      <GrossMass></GrossMass>
      <NetMass>550</NetMass>
    </InvoiceLine>
  </Invoice>
</Job>

XSLT的一部分:

<?xml version="1.0" encoding="UTF-8" ?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
      <xsl:element name="Job">

        <xsl:element name="Invoice">
          <xsl:apply-templates select="Job/Invoice/TotGrossMass"/>
          <xsl:apply-templates select="Job/Invoice/TotNetMass"/>
          <xsl:for-each select="Job/Invoice/InvoiceLine">
            <xsl:element name="InvoiceLine">
              <xsl:apply-templates select="LineNo"/>
              <xsl:apply-templates select="GrossMass"/>
              <xsl:apply-templates select="NetMass"/>
            </xsl:element>
          </xsl:for-each>
        </xsl:element>
      </xsl:element>
    </xsl:template>

    <xsl:template match="*">
      <xsl:element name="{name()}">
        <xsl:apply-templates/>
      </xsl:element>
    </xsl:template>

    <xsl:template match="GrossMass">
      <xsl:element name="{name()}">
        <xsl:value-of select="format-number(ancestor::Invoice/InvoiceLine/NetMass * ancestor::Invoice/TotGrossMass div ancestor::Invoice/TotNetMass,'#.##')"/>
      </xsl:element>
    </xsl:template>

  </xsl:stylesheet>

结果:

<?xml version="1.0" encoding="UTF-8"?>
    <Job xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
      <Invoice>
       <TotGrossMass>1853.80</TotGrossMass>
       <TotNetMass>1752.00</TotNetMass>
       <InvoiceLine>
          <LineNo>1</LineNo>
          <GrossMass>224.64</GrossMass>
          <NetMass>212.3</NetMass>
       </InvoiceLine>
       <InvoiceLine>
          <LineNo>2</LineNo>
          <GrossMass>224.64</GrossMass>
          <NetMass>212.3</NetMass>
       </InvoiceLine>
       <InvoiceLine>
          <LineNo>3</LineNo>
          <GrossMass>224.64</GrossMass>
          <NetMass>227.4</NetMass>
       </InvoiceLine>
       <InvoiceLine>
          <LineNo>4</LineNo>
          <GrossMass>224.64</GrossMass>
          <NetMass>550</NetMass>
       </InvoiceLine>
       <InvoiceLine>
          <LineNo>5</LineNo>
          <GrossMass>224.64</GrossMass>
          <NetMass>550</NetMass>
       </InvoiceLine>
     </Invoice>
   </Job>

1 个答案:

答案 0 :(得分:0)

之所以总是从第一个节点接收值,是因为后面的ancestorancestor::Invoice/InvoiceLine/NetMass始终使用第一个节点的值。

可以使用其他方法来简化XSLT。输入和输出XML结构几乎相同。在这种情况下,建议使用identity template,它会将所有输入XML节点/属性原样复制到输出。

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()" />
    </xsl:copy>
</xsl:template>

然后,GrossMass需要根据一些计算进行更新。为此,请覆盖GrossMass模板并执行计算。将TotGrossMassTotNetMass存储到变量中。同样,将同级NetMass值存储在另一个变量中。随着等式变得更具可读性,将值存储在变量中只是为了易于理解。

<xsl:template match="GrossMass">
    <xsl:copy>
        <xsl:variable name="totGrossMass" select="ancestor::Invoice/TotGrossMass" />
        <xsl:variable name="totNetMass" select="ancestor::Invoice/TotNetMass" />
        <xsl:variable name="netMass" select="../NetMass" />
        <xsl:value-of select="format-number(($netMass * $totGrossMass) div $totNetMass, '#.##')" />
    </xsl:copy>
</xsl:template>

完整的XSLT如下

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" />
    <xsl:strip-space elements="*" />

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()" />
        </xsl:copy>
    </xsl:template>

    <xsl:template match="GrossMass">
        <xsl:copy>
            <xsl:variable name="totGrossMass" select="ancestor::Invoice/TotGrossMass" />
            <xsl:variable name="totNetMass" select="ancestor::Invoice/TotNetMass" />
            <xsl:variable name="netMass" select="../NetMass" />
            <xsl:value-of select="format-number(($netMass * $totGrossMass) div $totNetMass, '#.##')" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

输出

<Job xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Invoice>
        <TotGrossMass>1853.80</TotGrossMass>
        <TotNetMass>1752.00</TotNetMass>
        <InvoiceLine>
            <LineNo>1</LineNo>
            <GrossMass>224.64</GrossMass>
            <NetMass>212.3</NetMass>
        </InvoiceLine>
        <InvoiceLine>
            <LineNo>2</LineNo>
            <GrossMass>224.64</GrossMass>
            <NetMass>212.3</NetMass>
        </InvoiceLine>
        <InvoiceLine>
            <LineNo>3</LineNo>
            <GrossMass>240.61</GrossMass>
            <NetMass>227.4</NetMass>
        </InvoiceLine>
        <InvoiceLine>
            <LineNo>4</LineNo>
            <GrossMass>581.96</GrossMass>
            <NetMass>550</NetMass>
        </InvoiceLine>
        <InvoiceLine>
            <LineNo>5</LineNo>
            <GrossMass>581.96</GrossMass>
            <NetMass>550</NetMass>
        </InvoiceLine>
    </Invoice>
</Job>