使用XSL从XML中进行选择

时间:2013-01-03 19:07:21

标签: xml xslt

我不知道如何正确命名主题以指定我的问题:) 我的XML数据库如下所示:

<data>
<prices>
<ROW>
<COLUMN NAME="product_id">00932932</COLUMN>
<COLUMN NAME="price">56</COLUMN>
... some other not irrelevant columns
</ROW>
... other rows with the same columns
</prices>
</data>

我试图选择价格高于30且颜色为绿色的那些。但它标志着所有的价格都是绿色的,好像这些条件对所有人来说都是正确的。 条件如下:

<xsl:if test='/data/prices/ROW[COLUMN[@NAME="price"] &gt; 30]' >
<span style="color: green"><xsl:value-of select='/data/prices/ROW[COLUMN[@NAME="EXPIRATION_DATE"]="" and COLUMN[@NAME="PRODUCT_ID"]=current()/COLUMN[@NAME="PRODUCT_ID"] ]/COLUMN[@NAME="PRICE"]'/></span>
</xsl:if>
<xsl:if test='/data/prices/ROW[COLUMN[@NAME="PRICE"] &lt; 30]' >
<xsl:value-of select='/data/prices/ROW[COLUMN[@NAME="EXPIRATION_DATE"]="" and COLUMN[@NAME="PRODUCT_ID"]=current()/COLUMN[@NAME="PRODUCT_ID"] ]/COLUMN[@NAME="PRICE"]'/>
</xsl:if>

任何帮助将不胜感激:)

5 个答案:

答案 0 :(得分:3)

问题可能是你的xsl:if正在测试任何 ROW行的价格是否大于30,无论你当前的上下文是什么(即不管你当前定位的是哪一行)上)。 / xpath表达式的开头意味着您在文档节点处开始搜索,而不是当前节点。

假设您正在选择包含模板的所有行(或者您正在执行 xsl:for-each

<xsl:apply-templates select="ROW">

然后,在与ROW匹配的模板中,您可以将 xsl:if 编码为

<xsl:if test='COLUMN[@NAME="price"] &gt; 30'>

以下是一个用于演示

的XSLT示例
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:template match="/data/prices">
      <table>
      <xsl:apply-templates select="ROW" />
      </table>
   </xsl:template>

   <xsl:template match="ROW">
      <tr>
         <xsl:if test="COLUMN[@NAME='price'] &gt; 30">
            <xsl:attribute name="style">background-color:green</xsl:attribute>
         </xsl:if>
         <td><xsl:value-of select="COLUMN[@NAME='product_id']" /></td>
         <td><xsl:value-of select="COLUMN[@NAME='price']" /></td>
      </tr>
   </xsl:template>   
</xsl:stylesheet>

答案 1 :(得分:0)

您的XPath表达式与您显示的XML不匹配。 data元素在XML中不可见(我假设您为简单起见省略了这一点),但ROW元素都不是。此外,您需要了解区分大小写 - 即在XPath中需要columnname(小写)(反之亦然)。一定有其他错误,因为在给定的情况下,所有元素的条件都是错误的。

答案 2 :(得分:0)

我的朋友没有展示一切(让我们这样称呼)。 我们必须写一个脚本(我朋友之前说的)颜色价格高于30。 这段代码正在运行。它显示了我们需要的一切:

        <xsl:for-each select='/dane/produkty/ROW'>
                    <tr style="border-style: solid">
                        <td style="border-style: solid">
                            <xsl:value-of select='COLUMN[@NAME="ID_PRODUKTU"]'/>
                        </td>
                        <td style="border-style: solid">
                            <xsl:value-of select='COLUMN[@NAME="OPIS"]'/>
                        </td>
                        <td style="border-style: solid">
                        <xsl:if test='/dane/ceny/ROW[COLUMN[@NAME="CENA_CENNIKOWA"] ] ' >
                            <span style="color: green"><xsl:value-of select='/dane/ceny/ROW[COLUMN[@NAME="DATA_WYCOFANIA"]="" and COLUMN[@NAME="ID_PRODUKTU"]=current()/COLUMN[@NAME="ID_PRODUKTU"] ]/COLUMN[@NAME="CENA_CENNIKOWA"]'/></span>
                        </xsl:if>

                        <!--<xsl:if test='/dane/ceny/ROW[COLUMN[@NAME="CENA_CENNIKOWA"] &lt; "31"]' >
                            <xsl:value-of select='/dane/ceny/ROW[COLUMN[@NAME="DATA_WYCOFANIA"]="" and COLUMN[@NAME="ID_PRODUKTU"]=current()/COLUMN[@NAME="ID_PRODUKTU"] ]/COLUMN[@NAME="CENA_CENNIKOWA"]'/>
                        </xsl:if>-->
                        </td>
                    </tr>
                </xsl:for-each>

这将为每个价格着色,但我们必须使用条件。

答案 3 :(得分:0)

回答matyo35的回复问题:

<xsl:if test='/dane/ceny/ROW[COLUMN[@NAME="CENA_CENNIKOWA"] ] ' >
 <span style="color: green"><xsl:value-of 
  select='/dane/ceny/ROW[COLUMN[@NAME="DATA_WYCOFANIA"]="" 
                       and COLUMN[@NAME="ID_PRODUKTU"]=current()/COLUMN[@NAME="ID_PRODUKTU"] ]
                                  /COLUMN[@NAME="CENA_CENNIKOWA"]'/></span>
</xsl:if>

test attributr中的条件始终满足,如果有一个Row有一个孩子COLUMN[@NAME="CENA_CENNIKOWA"],因为表达式是绝对的 - - 它不依赖于当前节点,与模板匹配。

正确的方式(我猜 - 由于没有提供XML文档)指定条件

<xsl:if test=
  '/dane/ceny/ROW[COLUMN[NAME="ID_PRODUKTU"]=current()/COLUMN[NAME="ID_PRODUKTU"] 
                and COLUMN[@NAME="CENA_CENNIKOWA"] > 30]'>

答案 4 :(得分:0)

感谢Dimitre,但它仍然是一样的。所有价格都是绿色的。我发布了整个代码。我想这会更好:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" doctype-public='-//W3C//DTD XHTML 1.0 Strict//EN'doctype-system='http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'/>
<xsl:template match="/">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
        <head>
            <title>Zadanie 21</title>
            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        </head>
        <body>
            <table style="border-style: solid">
                <tr style="border-style: solid">
                    <td style="border-style: solid">ID</td>
                    <td style="border-style: solid">Produkt</td>
                    <td style="border-style: solid">Cena</td>
                </tr>
                <xsl:for-each select='/dane/produkty/ROW'>
                    <tr style="border-style: solid">
                        <td style="border-style: solid">
                            <xsl:value-of select='COLUMN[@NAME="ID_PRODUKTU"]'/>
                        </td>
                        <td style="border-style: solid">
                            <xsl:value-of select='COLUMN[@NAME="OPIS"]'/>
                        </td>
                        <td style="border-style: solid">
                        <xsl:if test='/dane/ceny/ROW[COLUMN[@NAME="CENA_CENNIKOWA"] &gt; 30] ' >
                            <span style="color: green"><xsl:value-of select='/dane/ceny/ROW[COLUMN[@NAME="DATA_WYCOFANIA"]="" and COLUMN[@NAME="ID_PRODUKTU"]=current()/COLUMN[@NAME="ID_PRODUKTU"] ]/COLUMN[@NAME="CENA_CENNIKOWA"]'/></span>
                        </xsl:if>
                        <xsl:if test='/dane/ceny/ROW[COLUMN[@NAME="CENA_CENNIKOWA"] &lt; 31]' >
                            <xsl:value-of select='/dane/ceny/ROW[COLUMN[@NAME="DATA_WYCOFANIA"]="" and COLUMN[@NAME="ID_PRODUKTU"]=current()/COLUMN[@NAME="ID_PRODUKTU"] ]/COLUMN[@NAME="CENA_CENNIKOWA"]'/>
                        </xsl:if>
                        </td>
                    </tr>
                </xsl:for-each>
            </table>
        </body>
    </html>
</xsl:template>