【问题标题】:xsl:choose being applied to all elements, not just the ones I wantxsl:choose 应用于所有元素,而不仅仅是我想要的元素
【发布时间】:2014-09-02 10:40:16
【问题描述】:

首先我会发布我的所有代码:

XML:

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE catalog SYSTEM "test.dtd">

<?xml-stylesheet type="text/xsl" href="test.xsl"?>
<catalog>
    <product category="art" id="id_001">
        <title>Blue Sculpture</title>
        <price currency="AUS">2000</price>
        <creation_date>
            <day>11</day>
            <month>08</month>
            <year format="yyyy">2014</year>
        </creation_date>
        <weight unit="kilogram">2</weight>
        <color>Green</color>
        <description>A beutiful Green Sculpture</description>
    </product>
    <product category="ovenware" id="id_002">
        <title>Red Pie Dish</title>
        <price currency="AUS">400</price>
        <creation_date>
            <day>5</day>
            <month>11</month>
            <year format="yyyy">2013</year>
        </creation_date>
        <weight unit="kilogram">5</weight>
        <color>Red</color>
        <description>Versatile Pie Dish!</description>
    </product>
    <product category="dinner_set" id="id_003">
        <title>Blue Sculpture</title>
        <price currency="AUS">2000</price>
        <creation_date>
            <day>11</day>
            <month>08</month>
            <year format="yyyy">2014</year>
        </creation_date>
        <weight unit="ton">2</weight>
        <color>Green</color>
        <description>A beutiful Green Sculpture</description>
    </product>
</catalog>

XSL:

<?xml version="1.0" encoding="ISO-8859-1"?>

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

<xsl:template match="/">
<html>
<link rel="stylesheet" type="text/css" href="test.css" />
<p>Artworks</p>
<table>
  <tr>
    <th>Title</th>
    <th>Price</th>
    <th>Creation Date</th>
    <th>Weight</th>
    <th>Color</th>
    <th>Description</th>
  </tr>
    <xsl:for-each select="catalog/product[@category='art']">
        <xsl:sort select="@id" data-type="number"/>
    <tr>
    <td><xsl:value-of select="title"/></td>
    <td>
        <span>&#36;</span>
        <xsl:value-of select="price"/>
    </td>
    <td>
        <xsl:value-of select="creation_date/day"/>
        <span>&#47;</span>
        <xsl:value-of select="creation_date/month"/>
        <span>&#47;</span>
        <xsl:value-of select="creation_date/year"/>
    </td>
    <td><xsl:value-of select="weight"/>
        <xsl:choose>
            <xsl:when test="//weight[@unit = 'gram']">
                <span>g</span>
            </xsl:when>
            <xsl:when test="//weight[@unit = 'kilogram']">
                <span>&#32;Kg</span>
            </xsl:when>
            <xsl:otherwise>
                <xsl:if test="//weight > 1">
                <span>&#32;Tonnes</span>
                </xsl:if>
                <xsl:if test="//weight &lt;= 1">
                <span>&#32;Ton</span>
                </xsl:if>
            </xsl:otherwise>
        </xsl:choose>
    </td>
    <td><xsl:value-of select="color"/></td>
    <td class="description"><xsl:value-of select="description"/></td>
    </tr>
    </xsl:for-each>
</table>

<p>Ovenware</p>
<table>
  <tr>
    <th>Title</th>
    <th>Price</th>
    <th>Creation Date</th>
    <th>Weight</th>
    <th>Color</th>
    <th>Description</th>
  </tr>
    <xsl:for-each select="catalog/product[@category='ovenware']">
        <xsl:sort select="id"/>
    <tr>
    <td><xsl:value-of select="title"/></td>
    <td>
        <span>&#36;</span>
        <xsl:value-of select="price"/>
    </td>
    <td>
        <xsl:value-of select="creation_date/day"/>
        <span>&#47;</span>
        <xsl:value-of select="creation_date/month"/>
        <span>&#47;</span>
        <xsl:value-of select="creation_date/year"/>
    </td>
    <td><xsl:value-of select="weight"/>
        <xsl:choose>
            <xsl:when test="//weight[@unit = 'gram']">
                <span>g</span>
            </xsl:when>
            <xsl:when test="//weight[@unit = 'kilogram']">
                <span>&#32;Kg</span>
            </xsl:when>
            <xsl:otherwise>
                <xsl:if test="//weight > 1">
                <span>&#32;Tonnes</span>
                </xsl:if>
                <xsl:if test="//weight &lt;= 1">
                <span>&#32;Ton</span>
                </xsl:if>
            </xsl:otherwise>
        </xsl:choose>
    </td>
    <td><xsl:value-of select="color"/></td>
    <td class="description"><xsl:value-of select="description"/></td>
    </tr>
    </xsl:for-each>
</table>

<p>Dinner Set's</p>
<table>
  <tr>
    <th>Title</th>
    <th>Price</th>
    <th>Creation Date</th>
    <th>Weight</th>
    <th>Color</th>
    <th>Description</th>
  </tr>
    <xsl:for-each select="catalog/product[@category='dinner_set']">
        <xsl:sort select="id"/>
    <tr>
    <td><xsl:value-of select="title"/></td>
    <td>
        <span>&#36;</span>
        <xsl:value-of select="price"/>
    </td>
    <td>
        <xsl:value-of select="creation_date/day"/>
        <span>&#47;</span>
        <xsl:value-of select="creation_date/month"/>
        <span>&#47;</span>
        <xsl:value-of select="creation_date/year"/>
    </td>
    <td><xsl:value-of select="weight"/>
        <xsl:choose>
            <xsl:when test="//weight[@unit = 'gram']">
                <span>g</span>
            </xsl:when>
            <xsl:when test="//weight[@unit = 'kilogram']">
                <span>&#32;Kg</span>
            </xsl:when>
            <xsl:otherwise>
                <xsl:if test="//weight > 1">
                <span>&#32;Tonnes</span>
                </xsl:if>
                <xsl:if test="//weight &lt;= 1">
                <span>&#32;Ton</span>
                </xsl:if>
            </xsl:otherwise>
        </xsl:choose>
    </td>
    <td><xsl:value-of select="color"/></td>
    <td class="description"><xsl:value-of select="description"/></td>
    </tr>
    </xsl:for-each>
</table>
</html>
</xsl:template>



</xsl:stylesheet>

如果你想看看,我的 DTD:

<!ELEMENT catalog (product+)>
<!ELEMENT product (title?, price, creation_date?, weight?, color, description?)>
<!ELEMENT creation_date (day, month, year)>

<!ATTLIST product id ID #REQUIRED>
<!ATTLIST product category (art|dinner_set|ovenware) "art">
<!ATTLIST price currency (AUS|USA) "AUS">
<!ATTLIST weight unit (gram|kilogram|ton) "gram">
<!ATTLIST year format (yy|yyyy) "yy">


<!ELEMENT id (#PCDATA)>
<!ELEMENT title (#PCDATA)>
<!ELEMENT price (#PCDATA)>
<!ELEMENT day (#PCDATA)>
<!ELEMENT month (#PCDATA)>
<!ELEMENT year (#PCDATA)>
<!ELEMENT weight (#PCDATA)>
<!ELEMENT color (#PCDATA)>
<!ELEMENT description (#PCDATA)>.

还有 Css,所以你们可以正常运行:)

body{
    background-color: #fff;

}
table{
    border-collapse:collapse;
    border-spacing:0;
    padding: 10px;
    width: 100%;
    overflow: hidden;
}
td{
    font-family:Arial, sans-serif;
    font-size:14px;
    padding:10px 5px;
    overflow:hidden;
    word-break:normal;
    min-width: 80px;
    text-align: center;
    background-color: #E0E5DF;
    border-bottom: 2px solid #f6f6f6;
    border-top: 2px solid #f6f6f6;
}
th{
    font-family:Arial, sans-serif;
    font-size:14px;
    font-weight:normal;
    padding:10px 5px;
    overflow:hidden;
    word-break:normal;
    border-top: 4px solid #32517F;
    border-bottom: 2px solid #f6f6f6;
    background-color: #64A2FF;
}
tr:hover td{
    background-color: #81BDF7;
}
.description{
    width: 20%;
}

好的,如果您将所有这些都发布在一个文件夹中并将它们全部命名为“test.(无论扩展名是什么)”。所以 test.xml、test.dtd 等等。

所以真正的问题是这里的这段代码:

<td><xsl:value-of select="weight"/>
    <xsl:choose>
        <xsl:when test="//weight[@unit = 'gram']">
            <span>g</span>
        </xsl:when>
        <xsl:when test="//weight[@unit = 'kilogram']">
            <span>&#32;Kg</span>
        </xsl:when>
        <xsl:otherwise>
            <xsl:if test="//weight > 1">
            <span>&#32;Tonnes</span>
            </xsl:if>
            <xsl:if test="//weight &lt;= 1">
            <span>&#32;Ton</span>
            </xsl:if>
        </xsl:otherwise>
    </xsl:choose>
</td>

它的意思是检查属性“单位”,然后根据它的值在实际重量的末尾附加一个 g、kg 或 ton。这部分工作得很好。问题是它使用第一个并将其应用于所有三个表。

因此,例如在我的 xml 中,如果第一个产品的重量、属性单位设置为 kg,那么所有表中的每个产品都设置为 kg。

希望我已经很好地解释了这一点,并且它实际上是有道理的。我把所有的代码都贴出来了,大家可以自己运行,看起来比解释清楚更容易。

谢谢,

乔尔

【问题讨论】:

  • 刚刚意识到我认为问题出在 //weight,这是否会导致它搜索整个文档而不管父母是谁?不确定…………
  • 提供一个完整的例子很好;提供一个 minimal 完整的工作示例会更好。对智者说一句话……
  • 好点,以后我会领导你的智慧

标签: xml xslt xslt-1.0 dtd


【解决方案1】:

weightproduct 的子代,因此当您处于product 的上下文中时,对当前产品重量的正确引用是./weight 或只是weight - 而不是//weight,从根开始。

与您的问题无关,但您不应为每个类别重复相同的代码。


编辑:

还有关于如何做到这一点的任何建议......

以下是经过一些精简后的示例:

<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="/catalog">
    <html>
        <link rel="stylesheet" type="text/css" href="test.css" />
        <xsl:variable name="thead">
            <tr>
                <th>Title</th>
                <th>Price</th>
                <th>Creation Date</th>
                <th>Weight</th>
                <th>Color</th>
                <th>Description</th>
            </tr>
        </xsl:variable>
        <p>Artworks</p>
        <table>
            <xsl:copy-of select="$thead"/>
            <xsl:apply-templates select="product[@category='art']">
                <xsl:sort select="@id" data-type="number"/>
            </xsl:apply-templates>
        </table>
        <p>Ovenware</p>
        <table>
            <xsl:copy-of select="$thead"/>
            <xsl:apply-templates select="product[@category='ovenware']">
                <xsl:sort select="@id" data-type="number"/>
            </xsl:apply-templates>
        </table>
        <p>Dinner Sets</p>
        <table>
            <xsl:copy-of select="$thead"/>
            <xsl:apply-templates select="product[@category='dinner_set']">
                <xsl:sort select="@id" data-type="number"/>
            </xsl:apply-templates>
        </table>
    </html>
</xsl:template>

<xsl:template match="product">          
    <tr>
        <td><xsl:value-of select="title"/></td>
        <td><xsl:value-of select="format-number(price, '$0')"/></td>
        <td>
            <xsl:value-of select="concat(creation_date/day, '/', creation_date/month, '/', creation_date/year)"/></td>
        <td>
            <xsl:value-of select="weight"/>
            <xsl:choose>
                <xsl:when test="weight/@unit = 'gram'">g</xsl:when>
                <xsl:when test="weight/@unit = 'kilogram'"> Kg</xsl:when>
                <xsl:otherwise>
                    <xsl:text> Ton</xsl:text>
                    <xsl:if test="weight > 1">nes</xsl:if>
                </xsl:otherwise>
            </xsl:choose>
        </td>
        <td><xsl:value-of select="color"/></td>
        <td class="description"><xsl:value-of select="description"/></td>
    </tr>
</xsl:template>

</xsl:stylesheet>

这可以通过循环一个类别列表来进一步实现——要么是保存在样式表或单独文档中的静态列表,要么是通过从处理的 XML 中提取唯一类别而派生的动态列表。

【讨论】:

  • 感谢您解决了这个小问题。至于重复的代码,我明白了,仍然首先让它正常工作。更大的 xml 数据共享方案的一部分。
  • 还有关于如何做到这一点的任何建议......我有点精神障碍。我猜它是一个,但是你如何正确地将它们添加到每个表中?
  • @Joel "我猜每个人都是一个" 实际上,在这里应用专用模板会更有效率 - 请参阅我的帖子的编辑。
猜你喜欢
  • 2015-08-08
  • 2012-07-11
  • 2021-09-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-08
  • 2016-07-31
  • 2017-04-15
相关资源
最近更新 更多