开发者

XML, XPATH adding values

i have XML files which contain records with the following stru开发者_运维百科cture:

<xml>
   <payment contractType="1">
     <income type="0">
       <gr code="1" amount="1506.00"/>
       <gr code="4" amount="35.00"/>
       <gr code="10" amount="288.14"/>
       <de code="3011300" amount="138.72"/>
       <de code="3081100" amount="48"/>
       <de code="3082400" amount="110"/>
     </income>
     <netAmount1 value="765.00"/>
    <netAmount2 value="765.00"/>
  </payment> 
 <payment contractType="1">
     <income type="0">
       <gr code="1" amount="506.00"/>
       <gr code="4" amount="35.00"/>
       <gr code="10" amount="0"/>
       <de code="3011300" amount="1.28"/>
       <de code="3081100" amount="48"/>
       <de code="3082400" amount="120"/>
     </income>
     <netAmount1 value="635.00"/>
    <netAmount2 value="635.00"/>
  </payment> 
</xml>

each file has many records of type payment and i want the final xml to contain one payment record by adding all the amount values for every differrent code value the result of the xml above is

<xml>  
  <payment contractType="1">
     <income type="0">
       <gr code="1" amount="2512.00"/>
       <gr code="4" amount="70.00"/>
       <gr code="10" amount="288.14"/>
       <de code="3011300" amount="140"/>
       <de code="3081100" amount="96"/>
       <de code="3082400" amount="230"/>
     </income>
     <netAmount1 value="1400.00"/>
    <netAmount2 value="1400.00"/>
  </payment> 
</xml>

I think XPath can be used for this, but I never used it before , could someone show me some Java (or else) code for this?


Good examples of XPath: http://www.w3schools.com/XPath/xpath_examples.asp taking into account your example, you will easy get it based on that. Examples are based on JavaScript
And diving into your propblem, I think what you need is xslt transformation, create another xml file based on given. Here is similar example, quite simplified. To calculate summary of <gr> amount you need to perform something like:

sum(//gr/@amount)

UPDATE: Well, just decided to play a bit with that. What I did:

1) Take Eclipse IDE
2) create project with your xml file
3) create xsl file like that:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">

        <totalpayment>

             <xsl:value-of select='sum(//@amount)'/>

        </totalpayment>

    </xsl:template>
</xsl:stylesheet>

4) Right click on that xsl file and execute "Run As.../XSL Transformation"
5) select your xml file from workspace and you get the result:

<?xml version="1.0" encoding="UTF-8"?><totalpayment>2126.5099999999998</totalpayment>
  • inside tag you get total amount (yeah, not precise, just read about sum and xslt to get how to improve calculating to get exact sum).

I don't know what's the result structure should be, so just created an example how to get anything, now you can play with that.

Little explanation: sum(//@amount) - it takes all tags with attribute amount and calculates sum of amount values

UPDATE2, according to input/output example

Try this XSLT transformation out:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />
    <xsl:key name="names" match="//*" use="local-name(.)" />

    <xsl:template match="/">
        <payment contractType="1">
            <income type="0">
                <xsl:for-each select="//@code[not(.=preceding::*//@code)]">
                    <xsl:variable name="tagname">
                        <xsl:value-of select="name(//*[@code=current()])" />
                    </xsl:variable>

                    <xsl:element name="{$tagname}">
                        <xsl:attribute name="code"> 
                            <xsl:value-of select="current()" />
                        </xsl:attribute>
                        <xsl:attribute name="amount">
                            <xsl:value-of select="sum(//*[@code=current()]/@amount)" /><br />
                        </xsl:attribute>
                    </xsl:element>
                </xsl:for-each>

                <xsl:for-each select="//*[generate-id(.) = generate-id(key('names', local-name(.))) and starts-with(name(),'netAmount')]">
                    <xsl:variable name="tagname">
                        <xsl:value-of select="name()" />
                    </xsl:variable>

                    <xsl:element name="{name()}">
                        <xsl:attribute name="value">
                            <xsl:value-of select="sum(//*[name()=$tagname]/@value)"></xsl:value-of>
                        </xsl:attribute>
                    </xsl:element>
                </xsl:for-each>

            </income>
        </payment>
    </xsl:template>
</xsl:stylesheet>

I've just executed this xsl with xml you had given, and I've got the same result you need:

<?xml version="1.0" encoding="UTF-8"?>
<payment contractType="1">
<income type="0">
<gr code="1" amount="2012"/>
<gr code="4" amount="70"/>
<gr code="10" amount="288.14"/>
<de code="3011300" amount="140"/>
<de code="3081100" amount="96"/>
<de code="3082400" amount="230"/>
<netAmount1 value="1400"/>
<netAmount2 value="1400"/>
</income>
</payment>

Except for value <gr code="1" amount="2512.00"/> - I don't know why 2512.00.

I don't know if that xslt is ready to use by you, or it is not that general, but I hope this is good start!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜