我想匹配特定节点值的第一次出现,我感到难过。
我尝试了<xsl:when test="root/content/contentType = root/content/contentType[.='generic'][1]">
,但它与每次出现都匹配,<xsl:when test="root/content/contentType[.='generic'][1]">
我想在下面输出HTML。第一个项目有一个标题,但每个项目都有一个相同值的类。
这是我的XML。
非常感谢任何想法。
XML:
<root>
<content>
<contentType>ingredients</contentType>
<listItems>
<item>Item 1</item>
<item>Item 2</item>
</listItems>
</content>
<content>
<contentType>generic</contentType>
<listItems>
<item>Item 1</item>
<item>Item 2</item>
</listItems>
</content>
<content>
<contentType>generic</contentType>
<listItems>
<item>Item 1</item>
<item>Item 2</item>
</listItems>
</content>
<content>
<contentType>ingredients</contentType>
<listItems>
<item>Item 1</item>
<item>Item 2</item>
</listItems>
</content>
<content>
<contentType>directions</contentType>
<listItems>
<item>Item 1</item>
<item>Item 2</item>
</listItems>
</content>
</root>
期望的输出:
<div class="ingredients">
<h2>Ingredients</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
<div class="generic">
<h2>Generic</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
<div class="generic">
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
<div class="ingredients">
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
<div class="directions">
<h2>Directions</h2>
<ul>
<li>Item 1</li>
<li>Item 2</li>
</ul>
</div>
编辑:
XSL:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<xsl:for-each select="root/content">
<div>
<xsl:attribute name="class"><xsl:value-of select="./contentType"/></xsl:attribute>
<xsl:choose>
<xsl:when test="./contentType[.='ingredients'][1]">
<h2><xsl:value-of select="./contentType"/></h2>
</xsl:when>
<xsl:when test="./contentType[.='generic'][1]">
<h2><xsl:value-of select="./contentType"/></h2>
</xsl:when>
<xsl:when test="./contentType[.='directions'][1]">
<h2><xsl:value-of select="./contentType"/></h2>
</xsl:when>
</xsl:choose>
<ul>
<xsl:for-each select="listItems/item">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:2)
如果您希望了解更多XSLT的乐趣,那么您可能有兴趣知道您可以使用一种名为“Muenchian Grouping”的技术来解决这个问题。实际上,您可以通过 contentType 元素对内容元素进行分组,并对组中的第一个元素采取特殊操作(即为其提供 h2 标题)
首先,您定义一个代表您的组的键
<xsl:key name="content" match="content" use="contentType"/>
因此,您正在寻找内容元素,并按 contentType 进行排列。
现在有点可怕的部分。您可以检查给定的内容元素是否是 contentType
组中第一个元素 <xsl:if test="generate-id() = generate-id(key('content', contentType)[1])">
为了解决此问题,key('content', contentType)[1]
会返回当前 contentType 键中的第一个内容元素。然后,您需要将其与当前内容元素进行比较,以查看它们是否相同。要执行此操作,请使用 generate-id ,它会返回任何元素的唯一ID。
试试这个XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="content" match="content" use="contentType"/>
<xsl:template match="root/content">
<div class="{contentType}">
<xsl:if test="generate-id() = generate-id(key('content', contentType)[1])">
<h2>
<xsl:value-of select="contentType"/>
</h2>
</xsl:if>
<xsl:apply-templates select="listItems"/>
</div>
</xsl:template>
<xsl:template match="listItems">
<ul>
<xsl:apply-templates select="item"/>
</ul>
</xsl:template>
<xsl:template match="item">
<li>
<xsl:value-of select="."/>
</li>
</xsl:template>
</xsl:stylesheet>
对于分组问题,Muenchian Grouping是解决问题的最有效方法。
答案 1 :(得分:0)
这个怎么样:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<xsl:for-each select="root/content">
<div class="{contentType}">
<xsl:if test="not(preceding::content[contentType = current()/contentType])">
<h2><xsl:value-of select="contentType"/></h2>
</xsl:if>
<ul>
<xsl:for-each select="listItems/item">
<li><xsl:value-of select="."/></li>
</xsl:for-each>
</ul>
</div>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
这可能更清洁一点:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="content">
<div class="{contentType}">
<xsl:if test="not(preceding::content[contentType = current()/contentType])">
<h2><xsl:value-of select="contentType"/></h2>
</xsl:if>
<ul>
<xsl:apply-templates select="listItems" />
</ul>
</div>
</xsl:template>
<xsl:template match="listItem/item">
<li><xsl:value-of select="."/></li>
</xsl:template>
</xsl:stylesheet>
这里的一个不一致是你想要的输出的h2值大写,而在这种情况下它们不会。你知道吗?
我认为好的做法是将类和标题作为源XML中的单独值,但如果你真的想在两个地方使用相同的值,你可以通过这样做来大写第一个字母:
<h2><xsl:value-of select="concat(translate(substring(contentType, 1, 1),
'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
substring(contentType, 2))"/></h2>