【问题标题】:Calculating the total from identical tags计算相同标签的总数
【发布时间】:2014-11-27 23:20:17
【问题描述】:

请告知我如何实现以下转换。

我输入的 xml 格式。

 <Employees>
     <Employee>
            <Name>Don</Name>
            <Salary>5000</Salary>
            <Expense>1000</Expense>
            <Expense>500</Expense>
            <Expense>300</Expense>
    </Employee>
     <Employee>
            <Name>John</Name>
            <Salary>5000</Salary>
            <Expense>100</Expense>
            <Expense>400</Expense>
            <Tax>500</Tax>
            <Tax>200</Tax>
    </Employee>

输出应该是

<Employees>
     <Employee>
            <Name>Don</Name>
            <Salary>5000</Salary>
            <Expense>1800</Expense>
    </Employee>
     <Employee>
            <Name>John</Name>
            <Salary>6000</Salary>
            <Expense>500</Expense>
            <Tax>700</Tax>
    </Employee>

谢谢

【问题讨论】:

    标签: xml xslt xslt-1.0


    【解决方案1】:

    我相信我会这样做:

    XSLT 1.0

    <xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
    
    <xsl:template match="/Employees">
        <Employees>
            <xsl:for-each select="Employee">
                <Employee>
                    <xsl:copy-of select="Name"/>
                    <Salary>
                        <xsl:value-of select="sum(Salary)"/>
                    </Salary>
                    <Expense>
                        <xsl:value-of select="sum(Expense)"/>
                    </Expense>
                    <Tax>
                        <xsl:value-of select="sum(Tax)"/>
                    </Tax>              
                </Employee>
            </xsl:for-each>
        </Employees>
    </xsl:template>
    
    </xsl:stylesheet>
    

    结果(与预期略有不同):

    <?xml version="1.0" encoding="utf-8"?>
    <Employees>
       <Employee>
          <Name>Don</Name>
          <Salary>5000</Salary>
          <Expense>1800</Expense>
          <Tax>0</Tax>
       </Employee>
       <Employee>
          <Name>John</Name>
          <Salary>5000</Salary>
          <Expense>500</Expense>
          <Tax>700</Tax>
       </Employee>
    </Employees>
    

    如果您愿意,可以有条件地输出任何或所有摘要,例如

    <xsl:if test="Tax">
        <Tax>
            <xsl:value-of select="sum(Tax)"/>
        </Tax>  
    </xsl:if>   
    

    【讨论】:

      【解决方案2】:

      您没有明确表明您尝试自己编写 XSLT 代码。我将向您展示如何处理Expense 元素。写

      • 执行身份转换以复制整个输入的模板
      • 匹配第一个 Expense 元素的模板,并使其内容为其父元素的所有 Expense 子元素的总和
      • 一个匹配后续 Expense 元素并且什么都不做的模板

      XML 输入

      假设以下格式正确的输入(在末尾添加&lt;/Employees&gt;):

      <Employees>
           <Employee>
                  <Name>Don</Name>
                  <Salary>5000</Salary>
                  <Expense>1000</Expense>
                  <Expense>500</Expense>
                  <Expense>300</Expense>
          </Employee>
           <Employee>
                  <Name>John</Name>
                  <Salary>5000</Salary>
                  <Expense>100</Expense>
                  <Expense>400</Expense>
                  <Tax>500</Tax>
                  <Tax>200</Tax>
          </Employee>
      </Employees>
      

      样式表

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      
       <xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="utf-8"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:template match="@*|node()">
         <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
         </xsl:copy>
       </xsl:template>
      
       <xsl:template match="Expense[1]">
         <xsl:copy>
            <xsl:value-of select="sum(../Expense)"/>
         </xsl:copy>
       </xsl:template>
      
       <xsl:template match="Expense"/>
      
      </xsl:stylesheet>
      

      XML 输出

      <?xml version="1.0" encoding="utf-8"?>
      <Employees>
         <Employee>
            <Name>Don</Name>
            <Salary>5000</Salary>
            <Expense>1800</Expense>
         </Employee>
         <Employee>
            <Name>John</Name>
            <Salary>5000</Salary>
            <Expense>500</Expense>
            <Tax>500</Tax>
            <Tax>200</Tax>
         </Employee>
      </Employees>
      

      要将这种处理应用于Employee 的任何子级,请使用类似

      <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
      
       <xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="utf-8"/>
       <xsl:strip-space elements="*"/>
      
       <xsl:template match="@*|node()">
         <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
         </xsl:copy>
       </xsl:template>
      
       <xsl:template match="*/*/*[count(../*[name() = current()/name()]) &gt; 1 and not(preceding-sibling::*[name() = current()/name()] ) ] ">
               <xsl:element name="{name()}">
                  <xsl:value-of select="sum(../*[name() = current()/name()])"/>
               </xsl:element>
       </xsl:template>
      
       <xsl:template match="*/*/*[preceding-sibling::*[name() = current()/name()]]"/>
      
      </xsl:stylesheet>
      

      结果

      <?xml version="1.0" encoding="utf-8"?>
      <Employees>
         <Employee>
            <Name>Don</Name>
            <Salary>5000</Salary>
            <Expense>1800</Expense>
         </Employee>
         <Employee>
            <Name>John</Name>
            <Salary>5000</Salary>
            <Expense>500</Expense>
            <Tax>700</Tax>
         </Employee>
      </Employees>
      

      并且还显示您的预期输出是错误的 - John 的工资当然应该保持 5000,而不是更改为 6000。

      【讨论】:

      • Expense[not(preceding-sibling::Expense)]Expense[1]有区别吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-16
      • 1970-01-01
      • 1970-01-01
      • 2013-01-13
      • 1970-01-01
      • 2013-05-08
      相关资源
      最近更新 更多