XSL for-each组合了不同的运营商

时间:2016-07-04 13:59:57

标签: xml xslt foreach operators

我有这个XML文件,我需要以三种方式过滤:

1)颜色应为红色或绿色,其他所有颜色都应过滤掉

2)类别可以是任何类别,但catB

除外

3)状态可以是任何状态,除了MISSING或DAMAGED

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="items.xsl"?>
<list>
<item>
<description>Green catA Damaged</description>
<include>N</include>
<colour>GREEN</colour>
<category>catA</category>
<status>DAMAGED</status>
</item>
<item>
<description>Red catA OK</description>
<include>Y</include>
<colour>RED</colour>
<category>catA</category>
<status>OK</status>
</item>
<item>
<description>Green catB OK</description>
<include>N</include>
<colour>GREEN</colour>
<category>catB</category>
<status>OK</status>
</item>
<item>
<description>Red catB OK</description>
<include>N</include>
<colour>RED</colour>
<category>catB</category>
<status>OK</status>
</item>
<item>
<description>Blue catB OK</description>
<include>N</include>
<colour>BLUE</colour>
<category>catC</category>
<status>OK</status>
</item>
<item>
<description>Yellow catC OK</description>
<include>N</include>
<colour>YELLOW</colour>
<category>catC</category>
<status>OK</status>
</item>
<item>
<description>Green catA OK</description>
<include>Y</include>
<colour>GREEN</colour>
<category>catA</category>
<status>OK</status>
</item>
<item>
<description>Green catB Missing</description>
<include>N</include>
<colour>GREEN</colour>
<category>catB</category>
<status>MISSING</status>
</item>
<item>
<description>Red catB Missing</description>
<include>N</include>
<colour>RED</colour>
<category>catA</category>
<status>MISSING</status>
</item>
<item>
<description>Red catC Damaged</description>
<include>N</include>
<colour>RED</colour>
<category>catC</category>
<status>DAMAGED</status>
</item>
</list>

我为第一个(正面)条件尝试了一个for-each,另一个用于其他两个(负面)条件 - 但是我应该如何将它们组合成一个?或者,是否有另一种更好的替代方案来代替for-each。 谷歌搜索和检查三本书没有给我答案,所以我有一种奇怪的感觉我完全错了.....

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:template match="/">
    <list>

            <!-- "positive" statement
        <xsl:for-each select="list/item[colour='GREEN' or colour='RED']">

            "negative" statement
        <xsl:for-each select="list/item[status!='MISSING'][status!='DAMAGED'][category!='catB']">
            -->


            <xsl:sort select="description"/>

                <itemline>
                    <description><xsl:value-of select="description"/></description>
                    <include><xsl:value-of select="include"/></include>
                    <colour><xsl:value-of select="colour"/></colour>
                    <category><xsl:value-of select="category"/></category>
                    <status><xsl:value-of select="status"/></status>
                </itemline>


        </xsl:for-each>
    </list>
</xsl:template>

</xsl:stylesheet>

2 个答案:

答案 0 :(得分:1)

  

1)颜色应为红色或绿色,所有其他颜色应过滤   远

     

2)类别可以是任何类别,但catB

除外      

3)状态可以是任何状态,除了MISSING或DAMAGED

怎么样:

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="/list">
    <list>
        <xsl:for-each select="item
                              [colour='RED' or colour='GREEN']
                              [not(category='catB')]
                              [not(status='MISSING' or status='DAMAGED')]">
            <xsl:sort select="description"/>
            <itemline>
                <xsl:copy-of select="*"/>
            </itemline>
        </xsl:for-each>
    </list>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:1)

  

我有这个XML文件,我需要以三种方式过滤:

     

1)颜色应为红色或绿色,所有其他颜色应过滤   远

     

2)类别可以是任何类别,但catB

除外      

3)状态可以是任何状态,除了MISSING或DAMAGED

我会这样写

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

  <xsl:template match="/*">
    <xsl:apply-templates select=
     "item[colour[. = 'RED' or . = 'GREEN'] 
          and not(category='catB' or status[. = 'MISSING' or . = 'DAMAGED'])]">
      <xsl:sort select="description"/>
    </xsl:apply-templates>
  </xsl:template>

  <xsl:template match="item">
    <itemline><xsl:copy-of select="*"/></itemline>
  </xsl:template>
</xsl:stylesheet>

如果使用<xsl:for-each> 非常重要(通常不是最好的XSLT做法),则上述内容相当于此转换:

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

  <xsl:template match="/*">
    <xsl:for-each select=
     "item[colour[. = 'RED' or . = 'GREEN'] 
          and not(category='catB' or status[. = 'MISSING' or . = 'DAMAGED'])]">
      <xsl:sort select="description"/>
      <itemline><xsl:copy-of select="*"/></itemline>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>

两种转换在应用于提供的XML文档时都会生成所需的正确结果

<itemline>
   <description>Green catA OK</description>
   <include>Y</include>
   <colour>GREEN</colour>
   <category>catA</category>
   <status>OK</status>
</itemline>
<itemline>
   <description>Red catA OK</description>
   <include>Y</include>
   <colour>RED</colour>
   <category>catA</category>
   <status>OK</status>
</itemline>

有用的快捷表达

而不是:

myElem = value1 or myElem = value2 or myElem = value3 or myElem = value4 or myElem = value5 

可以写下这个:

contains('|value1|value2|value3|value4|value5|', concat('|',myElem, '|'))

或者,如果第一个参数字符串是变量$myValues的值:

contains($myValues, concat('|',myElem, '|')) 

同样,myElem的值的快捷方式不是众多值中的一个

not(contains($myValues, concat('|',myElem, '|')))