从具有多个类别元素的XML节点中选择

时间:2012-01-14 06:45:12

标签: xslt

我有一个XML文档,其中包含已分配给多个类别的新闻文章集合。我现在需要按类别对这些文件进行分组。以下是样本项记录:

<item>
        <link>http://www.threelanews.com/articles/?id=50456</link>
        <category>/General/</category>
        <category>/Technology/</category>
        <category>/Technology/Telecommunications/</category>
        <category>/Technology/Information Technology/Internet/</category>
        <title>Sony debuts handsets at CES</title>
        <description>The Xperia S will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</description>
       <pubDate>Tue, 10 Jan 2012 12:11:01 +0200</pubDate>
</item>

我正在使用XSL样式表来转换文档。对于每个组,我将进行测试以查看属于该类别的元素,如果其中一个类别元素中存在匹配项,则应将该文章添加到html中,例如:

<xsl:when test="contains(category,'/General/')">
   <div class="news-item" width="100%">
      <div class="news-item-title" width="100%">
          <a href="{$linkUrl}" target="_blank">
             <xsl:value-of select="title"/>
          </a>
      </div>
      <xsl:if test="string-length($imageUrl) &gt; 0">
          <div class="news-item-image">
             <img src="{$imageUrl}" />
          </div>
      </xsl:if>
      <div class="news-item-description">
          <xsl:value-of select="description"/>
      </div>
   </div>
   <div class="clear" />
</xsl:when>

然后将该文章添加到&#34; General Group&#34;。具有多个类别的文章应出现在每个相关的组中。上述声明适用于&#34; General&#34;小组,但当我尝试为#34;技术&#34;或其下面的其他类别,本文不予退还。我发现它只是在第一个元素上进行匹配。我有什么方法可以对所有类别元素进行匹配吗?

2 个答案:

答案 0 :(得分:1)

尝试以下转换:

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

    <xsl:template match="/">
        <html>
            <body>
                <h2>Matched Items</h2>
                <xsl:apply-templates select=
                "//item[category/.='/General/']"/>
            </body>
        </html>
    </xsl:template>

    <xsl:template match="item">
        <div class="news-item" width="100%">
            <div class="news-item-title" width="100%">
                <a href="{linkUrl}" target="_blank">
                    <xsl:value-of select="title"/>
                </a>
            </div>
            <xsl:if test="string-length(imageUrl) &gt; 0">
                <div class="news-item-image">
                    <img src="{imageUrl}" />
                </div>
            </xsl:if>
            <div class="news-item-description">
                <xsl:value-of select="description"/>
            </div>
        </div>
        <div class="clear" />
    </xsl:template>
</xsl:stylesheet>

重要的部分是这个XPath,它选择具有给定值的类别的所有项目节点:

//item[category/.='/General/']

将转换应用于此文档:

<items>
    <item>
        <link>http://www.threelanews.com/articles/?id=50456</link>
        <category>/General/</category>
        <category>/Technology/</category>
        <category>/Technology/Telecommunications/</category>
        <category>/Technology/Information Technology/Internet/</category>
        <title>Sony debuts handsets at CES</title>
        <description>The Xperia S will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</description>
        <pubDate>Tue, 10 Jan 2012 12:11:01 +0200</pubDate>
    </item>
    <item>
        <link>http://www.threelanews.com/articles/?id=50456</link>
        <category>/Technology/</category>
        <category>/Technology/Telecommunications/</category>
        <category>/Technology/Information Technology/Internet/</category>
        <title>Sony debuts handsets at CES</title>
        <description>The Xperia S will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</description>
        <pubDate>Tue, 10 Jan 2012 12:11:01 +0200</pubDate>
    </item>
</items>

给出预期结果:

<H2>Matched Items</H2>
<DIV class=news-item width="100%">
  <DIV class=news-item-title width="100%"><A href="" target=_blank>Sony debuts handsets at CES</A></DIV>
  <DIV class=news-item-description>The Xperia S will be available globally from the first quarter of 2012. Sony Ericsson will showcase the first handsets from...</DIV>
</DIV>
<DIV class=clear></DIV>

答案 1 :(得分:0)

此转化

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

 <xsl:key name="kCategoryByVal" match="category"
  use="substring-before(substring(.,2), '/')"/>

 <xsl:template match=
  "category
     [generate-id()
     =
      generate-id(key('kCategoryByVal',
                      substring-before(substring(.,2), '/')
                      )
                       [1]
                  )
     ]

  ">
  <xsl:variable name="vMainCat" select=
       "substring-before(substring(.,2), '/')"/>

  <h1><xsl:value-of select="$vMainCat"/></h1>

  <xsl:apply-templates mode="inGroup" select=
   "/*/item[category[starts-with(., concat('/', $vMainCat))]]"/>
 </xsl:template>

 <xsl:template match="item" mode="inGroup">
   <div class="news-item" width="100%">
     <div class="news-item-title" width="100%">
       <a href="{link}" target="_blank">
         <xsl:value-of select="title"/>
       </a>
     </div>
      <xsl:apply-templates select="image[@url]" mode="inGroup"/>
     <div class="news-item-description">
      <xsl:value-of select="description"/>
     </div>
   </div>
   <div class="clear" />
 </xsl:template>

 <xsl:template match="image" mode="inGroup">
  <div class="news-item-image">
    <img src="{@url}" />
  </div>
 </xsl:template>
 <xsl:template match="text()"/>
</xsl:stylesheet>

应用于此XML文档(从提供的内容中派生出来,但更加真实一点):

<items>
    <item>
        <link>http://www.threelanews.com/articles/?id=50456</link>
        <category>/General/</category>
        <category>/Technology/</category>
        <category>/Technology/Telecommunications/</category>
        <category>/Technology/Information Technology/Internet/</category>
        <title>Sony debuts handsets at CES</title>
        <image url="http://www.blogcdn.com/www.engadget.com/media/2011/03/11x0328mar0424.jpg"/>
        <description>The Xperia S will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</description>
        <pubDate>Tue, 10 Jan 2012 12:11:01 +0200</pubDate>
    </item>
    <item>
        <link>http://www.threelanews.com/articles/?id=50456</link>
        <category>/Technology/</category>
        <category>/Technology/Telecommunications/</category>
        <category>/Technology/Information Technology/Internet/</category>
        <title>Toshiba produces the next Portege</title>
        <description>The next Portege will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</description>
        <pubDate>Tue, 10 Jan 2012 12:11:01 +0200</pubDate>
    </item>
</items>

生成所需结果(所有不同类别及其中的项目):

<h1>General</h1>
<div class="news-item" width="100%">
   <div class="news-item-title" width="100%">
      <a href="http://www.threelanews.com/articles/?id=50456" target="_blank">Sony debuts handsets at CES</a>
   </div>
   <div class="news-item-image">
      <img src="http://www.blogcdn.com/www.engadget.com/media/2011/03/11x0328mar0424.jpg"/>
   </div>
   <div class="news-item-description">The Xperia S will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</div>
</div>
<div class="clear"/>
<h1>Technology</h1>
<div class="news-item" width="100%">
   <div class="news-item-title" width="100%">
      <a href="http://www.threelanews.com/articles/?id=50456" target="_blank">Sony debuts handsets at CES</a>
   </div>
   <div class="news-item-image">
      <img src="http://www.blogcdn.com/www.engadget.com/media/2011/03/11x0328mar0424.jpg"/>
   </div>
   <div class="news-item-description">The Xperia S will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</div>
</div>
<div class="clear"/>
<div class="news-item" width="100%">
   <div class="news-item-title" width="100%">
      <a href="http://www.threelanews.com/articles/?id=50456" target="_blank">Toshiba produces the next Portege</a>
   </div>
   <div class="news-item-description">The next Portege will be available globally from the first quarter of 2012.&#xD;Sony Ericsson will showcase the first handsets from...</div>
</div>
<div class="clear"/>

<强>解释

  1. 使用 Muenchian grouping 找到所有不同的主要类别。

  2. 对于每个主要类别,所有item元素都具有category字符串值,使该项属于此主要类别,该项目的数据将按适当格式输出。

  3. 在此解决方案中,假设只需列出“主要”类别(字符串中包含类别和子类别的起始类别名称)。