0

我想匹配特定节点值的第一次出现,我很难过。

我已经尝试过<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>
4

2 回答 2

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 是解决问题的最有效方法。

于 2013-01-10T08:42:50.170 回答
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>
于 2013-01-10T01:24:47.750 回答