在添加多重类别后,使用XSLT对XML进行特定的样式设置

时间:2012-09-14 07:30:05

标签: xml xslt styling

所以我正在浏览w3schools上的XML教程,我遇到了关于使用XSLT设计XML样式的页面: http://www.w3schools.com/xml/tryxslt.asp?xmlfile=simple&xsltfile=simple

那里有一些简单的代码。我添加了两个主要食品类别<waffles><other> 代码,我想知道如何使用最小的XSLT来设置XML样式,以便所有<waffle> <food>具有橙色背景,所有<other><food>具有青色背景,而不必重复大块像我在下面做的代码。

您可以在上面的链接中看到原始代码,这是我的代码:

XML:

    <?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<breakfast_menu>
     <waffles>
    <food>
        <name>Belgian Waffles</name>
        <price>$5.95</price>
        <description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
        <calories>650</calories>
    </food>
    <food>
        <name>Strawberry Belgian Waffles</name>
        <price>$7.95</price>
        <description>light Belgian waffles covered with strawberries and whipped cream</description>
        <calories>900</calories>
    </food>
    <food>
        <name>Berry-Berry Belgian Waffles</name>
        <price>$8.95</price>
        <description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
        <calories>900</calories>
    </food>
     </waffles>
     <other>
    <food>
        <name>French Toast</name>
        <price>$4.50</price>
        <description>thick slices made from our homemade sourdough bread</description>
        <calories>600</calories>
    </food>
    <food>
        <name>Homestyle Breakfast</name>
        <price>$6.95</price>
        <description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
        <calories>950</calories>
    </food>
     <other>
</breakfast_menu>

XSLT:

<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
    <html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
      <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
    <xsl:for-each select="breakfast_menu/waffles">
        <div style="background-color:ORANGE;">
          <xsl:for-each select="food">
          <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold"><xsl:value-of select="name"/></span>
            - <xsl:value-of select="price"/>
          </div>
          <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
            <xsl:value-of select="description"/>
            <span style="font-style:italic">
              <xsl:value-of select="calories"/> (calories per serving)
            </span>
          </div>
         </xsl:for-each>
       </div>    
    </xsl:for-each>

    <xsl:for-each select="breakfast_menu/other">
        <div style="background-color:CYAN;">
          <xsl:for-each select="food">
          <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold"><xsl:value-of select="name"/></span>
            - <xsl:value-of select="price"/>
          </div>
          <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
            <xsl:value-of select="description"/>
            <span style="font-style:italic">
              <xsl:value-of select="calories"/> (calories per serving)
            </span>
          </div>
         </xsl:for-each>
       </div>    
    </xsl:for-each>

      </body>
    </html>

2 个答案:

答案 0 :(得分:1)

在这里,您可以充分利用模板的强大功能,这是XSLT最基本的概念之一。

您可以首先查找 breakfast_menu 元素的子元素

<xsl:apply-templates select="breakfast_menu/*"/>

然后你会有一个匹配这些元素的模板

<xsl:template match="breakfast_menu/*">

在此模板中,您可以使用 xsl:choose 来创建样式属性

  <div>
     <xsl:attribute name="style">
        <xsl:choose>
           <xsl:when test="local-name() = 'waffles'">background-color:ORANGE;</xsl:when>
           <xsl:when test="local-name() = 'other'">background-color:CYAN;</xsl:when>
        </xsl:choose>
     </xsl:attribute>

在这种情况下,这是完整的XSLT。注意也使用模板来匹配食物元素,以避免使用 xsl:for-each

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html" indent="yes"/>
   <xsl:template match="/">
      <html>
         <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
            <xsl:apply-templates select="breakfast_menu/*"/>
         </body>
      </html>
   </xsl:template>

   <xsl:template match="breakfast_menu/*">
      <div>
         <xsl:attribute name="style">
            <xsl:choose>
               <xsl:when test="local-name() = 'waffles'">background-color:ORANGE;</xsl:when>
               <xsl:when test="local-name() = 'other'">background-color:CYAN;</xsl:when>
            </xsl:choose>
         </xsl:attribute>
         <xsl:apply-templates select="food"/>
      </div>
   </xsl:template>

   <xsl:template match="food">
      <div style="background-color:teal;color:white;padding:4px">
         <span style="font-weight:bold">
            <xsl:value-of select="name"/>
         </span> - 
         <xsl:value-of select="price"/></div>
      <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
         <xsl:value-of select="description"/>
         <span style="font-style:italic">
            <xsl:value-of select="calories"/> (calories per serving) </span>
      </div>
   </xsl:template>
</xsl:stylesheet>

为避免使用 xsl:choose ,另一种稍微不同的方法是使用单独的模板来匹配 waffle 其他元素。只需将与“breakfast_menu / *”匹配的当前模板替换为以下两个模板即可。

<xsl:template match="breakfast_menu/waffles">
  <div style="background-color:ORANGE;">
     <xsl:apply-templates select="food"/>
  </div>
</xsl:template>

<xsl:template match="breakfast_menu/other">
  <div style="background-color:CYAN;">
     <xsl:apply-templates select="food"/>
  </div>
</xsl:template>

如果你有很多子元素,但想要一个默认的'值',你可以做这样的事情

<xsl:template match="breakfast_menu/waffles" priority="2">
  <div style="background-color:ORANGE;">
     <xsl:apply-templates select="food"/>
  </div>
</xsl:template>

<xsl:template match="breakfast_menu/*" priority="1">
  <div style="background-color:CYAN;">
     <xsl:apply-templates select="food"/>
  </div>
</xsl:template>

请注意在这种情况下使用优先级属性,因为两个模板都匹配 waffle 。除非您告诉XSLT处理器一个优先级高于另一个处理器,否则这将是一个错误。

答案 1 :(得分:0)

此转化

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

 <my:colors>
  <color>ORANGE</color>
  <color>CYAN</color>
 </my:colors>

 <xsl:variable name="vColors" select="document('')/*/my:colors/*"/>

 <xsl:template match="/">
    <html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
      <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
      <xsl:apply-templates/>
      </body>
    </html>
 </xsl:template>

 <xsl:template match="*[food]">
        <div style="background-color:{$vColors[2 -(name(current())='waffles')]};">
          <xsl:for-each select="food">
          <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold"><xsl:value-of select="name"/></span>
            - <xsl:value-of select="price"/>
          </div>
          <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">
            <xsl:value-of select="description"/>
            <span style="font-style:italic">
              <xsl:value-of select="calories"/> (calories per serving)
            </span>
          </div>
         </xsl:for-each>
       </div>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档时:

<breakfast_menu>
     <waffles>
    <food>
        <name>Belgian Waffles</name>
        <price>$5.95</price>
        <description>two of our famous Belgian Waffles with plenty of real maple syrup</description>
        <calories>650</calories>
    </food>
    <food>
        <name>Strawberry Belgian Waffles</name>
        <price>$7.95</price>
        <description>light Belgian waffles covered with strawberries and whipped cream</description>
        <calories>900</calories>
    </food>
    <food>
        <name>Berry-Berry Belgian Waffles</name>
        <price>$8.95</price>
        <description>light Belgian waffles covered with an assortment of fresh berries and whipped cream</description>
        <calories>900</calories>
    </food>
     </waffles>
     <other>
    <food>
        <name>French Toast</name>
        <price>$4.50</price>
        <description>thick slices made from our homemade sourdough bread</description>
        <calories>600</calories>
    </food>
    <food>
        <name>Homestyle Breakfast</name>
        <price>$6.95</price>
        <description>two eggs, bacon or sausage, toast, and our ever-popular hash browns</description>
        <calories>950</calories>
    </food>
     </other>
</breakfast_menu>

会产生想要的正确结果:

<html xmlns="http://www.w3.org/1999/xhtml">
   <body style="font-family:Arial;font-size:12pt;background-color:#EEEEEE">
      <div xmlns="" style="background-color:ORANGE;">
         <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold">Belgian Waffles</span>
            - $5.95</div>
         <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">two of our famous Belgian Waffles with plenty of real maple syrup<span style="font-style:italic">650 (calories per serving)
            </span>
         </div>
         <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold">Strawberry Belgian Waffles</span>
            - $7.95</div>
         <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">light Belgian waffles covered with strawberries and whipped cream<span style="font-style:italic">900 (calories per serving)
            </span>
         </div>
         <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold">Berry-Berry Belgian Waffles</span>
            - $8.95</div>
         <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">light Belgian waffles covered with an assortment of fresh berries and whipped cream<span style="font-style:italic">900 (calories per serving)
            </span>
         </div>
      </div>
      <div xmlns="" style="background-color:CYAN;">
         <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold">French Toast</span>
            - $4.50</div>
         <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">thick slices made from our homemade sourdough bread<span style="font-style:italic">600 (calories per serving)
            </span>
         </div>
         <div style="background-color:teal;color:white;padding:4px">
            <span style="font-weight:bold">Homestyle Breakfast</span>
            - $6.95</div>
         <div style="margin-left:20px;margin-bottom:1em;font-size:10pt">two eggs, bacon or sausage, toast, and our ever-popular hash browns<span style="font-style:italic">950 (calories per serving)
            </span>
         </div>
      </div>
   </body>
</html>

<强>解释

正确使用:

  1. Template 匹配。

  2. AVT s(属性值模板)。