一些前哨结果使用两个条件

时间:2011-02-18 13:35:24

标签: xslt

我必须转换xml文件,我应该检查字段id'0',字段id'1'和sum字段id'2'。例如,我有:

<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>

结果应为:

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

在那里我应该采用所有MAR线,并显示一些取决于字段id'1'的结果。

我的想法是,首先关闭所有循环(每个)和使用条件(何时)。也许有人提出更不合理的决定。

我添加了新笔记,如何检查数据是否如此:

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

第一个字段我尝试使用函数包含'MAR',其他字符串在' - '之前。但是当我尝试使用你的程序时,我卡住了。也许你可以为它提出一些建议吗?

4 个答案:

答案 0 :(得分:2)

此转化

<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>

应用于提供的XML文档时:

<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>

会产生想要的正确结果:

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

解释 Muenchian method for grouping 与定义为两个元素串联的键一起使用。

答案 1 :(得分:2)

<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>

正确反对您的样本:

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

答案 2 :(得分:2)

此样式表:

<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>

输出:

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

注意:按@id属性,总和组,动态元素名称进行分组,首先参数化@id。

答案 3 :(得分:0)

感谢您的回答,我使用Flack决定并做出一些修正:

<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和Alejandro的决定也很好而且很有用(也许更专业)。但是Dimitre更专注于我写的任务,例如他使用条件检查我们是否有第二个字段(我没有写过,不仅MAR可以有field2)。亚历杭德罗检查它使用参数,所以对我来说,搜索更多信息如何使用它是一个很好的教训,因为使用xsl语言我有不到一个月的经验。所以对我来说很难为我的工作准备你的程序。作为初学者,Flack文本对我来说更容易理解。