开发者

Some outpost result using two condition

开发者 https://www.devze.com 2023-02-11 16:33 出处:网络
I have to transform xml file where i should check field id \'0\', field id \'1\' and sum field id \'2\'. For example I have:

I have to transform xml file where i should check field id '0', field id '1' and sum field id '2'. For example I have:

<document>
    <line id="0">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">2</field>
    </line>
    <line id="1">
        <field id="0">MAR</field>
        <field id="1">doc2</field>
        <field id="2">3</field>
    </line>
    <line id="2">
        <field id="0">AAA></field>
        <field id="1">doc4</field>
    </line>
    <line id="3">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">4</field>
    </line>
</document>

result should be:

<type-MAR>
    <document>doc1</document>
    <sum>6</sum>
    </type-MAR>   
<type-MAR>
    <document>doc2</document>
    <sum>3</sum>
</type-MAR>

there I should take all MAR lines, and show some results which are depends of field id '1'.

My idea was, first off all do cycle(for each) and use condition(when). Maybe somebody offer more omptimal decision.

I add new note,开发者_StackOverflow how to check if data comes like that:

<field id="0">MAR999</field>
<field id="1">doc1-1231</field>

First field i try to use function contains 'MAR', others substring-before '-'. but I stuck when I try it use on Yours program. maybe you can take some advice for it?


This transformation:

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

 <xsl:key name="kLineById0Id1" match="line[field[@id=2]]"
  use="concat(field[@id=0],'+',field[@id=1])"/>

 <xsl:template match=
  "line[field[@id=2]
      and
        generate-id()
       =
        generate-id(key('kLineById0Id1',
                        concat(field[@id=0],
                               '+',field[@id=1])
                       )[1])
       ]
  ">
  <xsl:element name="type-{field[@id=0]}">
       <document>
        <xsl:value-of select="field[@id=1]"/>
       </document>
       <sum>
        <xsl:value-of select=
        "sum(key('kLineById0Id1',
                concat(field[@id=0],
                       '+',field[@id=1])
               )
               /field[@id=2]
           )
        "/>
       </sum>
     </xsl:element>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>

when applied on the provided XML document:

<document>
    <line id="0">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">2</field>
    </line>
    <line id="1">
        <field id="0">MAR</field>
        <field id="1">doc2</field>
        <field id="2">3</field>
    </line>
    <line id="2">
        <field id="0">AAA></field>
        <field id="1">doc4</field>
    </line>
    <line id="3">
        <field id="0">MAR</field>
        <field id="1">doc1</field>
        <field id="2">4</field>
    </line>
</document>

produces the wanted, correct result:

<type-MAR>
   <document>doc1</document>
   <sum>6</sum>
</type-MAR>
<type-MAR>
   <document>doc2</document>
   <sum>3</sum>
</type-MAR>

Explanation: The Muenchian method for grouping is used with the key defined as the concatenation of two elements.


<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="kLine" match="line" use="field[@id='1']"/>
    <xsl:template match="/*">
        <r>
            <xsl:apply-templates select="line
                [field[@id='0'] = 'MAR']
                [count(
                    . | key('kLine', field[@id='1'])[1]
                    ) = 1]
                "/>
        </r>
    </xsl:template>
    <xsl:template match="line">
        <type-MAR>
            <document>
                <xsl:value-of select="field[@id='1']"/>
            </document>
            <sum>
                <xsl:value-of select="
                    sum(
                        key('kLine', field[@id='1'])/
                        field[@id='2']
                        )"/>
            </sum>
        </type-MAR>
    </xsl:template>
</xsl:stylesheet>

Correct against your sample will be:

<r>
    <type-MAR>
        <document>doc1</document>
        <sum>6</sum>
    </type-MAR>
    <type-MAR>
        <document>doc2</document>
        <sum>3</sum>
    </type-MAR>
</r>


This stylesheet:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="kLineById0-Id1" match="line"
             use="concat(field[@id='0'],'+',field[@id='1'])"/>
    <xsl:param name="pId0" select="'MAR'"/>
    <xsl:template match="document">
        <result>
            <xsl:apply-templates select="line[generate-id()=
                                              generate-id(
                                                 key('kLineById0-Id1',
                                                     concat($pId0,
                                                            '+',
                                                            field[@id='1']
                                                     )
                                                 )[1]
                                              )]"/>
        </result>
    </xsl:template>
    <xsl:template match="line">
        <xsl:element name="type-{$pId0}">
            <document>
                <xsl:value-of select="field[@id='1']"/>
            </document>
            <sum>
                <xsl:value-of select="sum(key('kLineById0-Id1',
                                              concat(field[@id='0'],
                                                     '+',
                                                     field[@id='1']
                                              )
                                          )/field[@id='2']
                                      )"/>
            </sum>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

Output:

<result>
    <type-MAR>
        <document>doc1</document>
        <sum>6</sum>
    </type-MAR>
    <type-MAR>
        <document>doc2</document>
        <sum>3</sum>
    </type-MAR>
</result>

Note: Grouping by both @id attributes, sum group, dynamic element name, parameterized first @id.


Thanks for answers, I use Flack decision and make some correction:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:key name="kLine" match="line" use="substring(field[@id='1'],1,4)"/>
    <xsl:template match="/*">
        <document>
            <xsl:apply-templates select="line[contains(field[@id='0'], 'MAR')][count(. | key('kLine', substring(field[@id='1'],1,4))[1]) = 1]"/>
        </document>
    </xsl:template>
    <xsl:template match="line">
        <type-MAR>
            <document>
                <xsl:value-of select="substring(field[@id='1'],1,4)"/>
            </document>
            <sum>
                <xsl:value-of select="sum(key('kLine', substring(field[@id='1'],1,4))/field[@id='2'])"/>
            </sum>
        </type-MAR>
    </xsl:template>
</xsl:stylesheet>

Dimitre and Alejandro decisions are also good and useful(maybe more professional). But Dimitre more concentrate on my task which I wrote, for example he use condition to check if we have the second field(I didn't wrote that not only MAR could have field2). Alejandro to check it use parameter, so for me it was a good lesson to search more information how to use it, because with xsl language I have less than one month experience. So for me was difficult to prepair Yours programs for my work. Flack text was more understandable for me as a beginner.

0

精彩评论

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