XSLT - 分隔父节点和子节点

时间:2017-03-28 14:51:16

标签: xslt parent-child

我刚刚开始'玩'XSLT,我遇到了一个不容易为我解决的问题。

我收到了以下HTML代码:

<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr,...
    <ul>
        <li>The first entry</li>
        <li>The second entry</li>
        <li>The third entry</li>
    </ul>
    sed diam nonumy eirmod...
</p>

我的结果应如下:

<p>Lorem ipsum dolor sit amet, consetetur sadipscing elitr,...sed diam nonumy eirmod...</p>
<p>The first entry</p>
<p>The second entry</p>
<p>The third entry</p>

我尝试了一个解决方案,其中ul模板以结束p开头 - 标签如

<xsl:template match="//p/ul">
    <xsl:for-each select="li">
        </p>
        <xsl:apply-templates/>
        <p>
    </xsl:for-each>
</xsl:template>

但这不是正确的XSLT方式。另一种方法是使用这种黑客

<xsl:text disable-output-escaping="yes"><![CDATA[</p>]]></xsl:text>

但我不确定是否还有其他更好的解决方案来解决我的问题。

感谢任何帮助!

3 个答案:

答案 0 :(得分:0)

这有点粗糙,但你可以试试这个:

<xsl:template match="*[text()]">
  <xsl:variable name="text">
    <xsl:copy-of select="text()"/>
  </xsl:variable>
  <xsl:if test="normalize-space($text)">
    <p><xsl:value-of select="normalize-space($text)"/></p>
  </xsl:if>
  <xsl:apply-templates select="*"/>
</xsl:template>

这会将任意节点与文本匹配,但如果您需要限制,则tou可以将其限制为"p[text()] | li[text()]"

它首先将文本放在变量中,以便更容易去掉空格。

答案 1 :(得分:0)

我认为您可以简化当前模板以匹配li

<xsl:template match="li">
    <p>
        <xsl:apply-templates/>
    </p>
</xsl:template>

如果您只希望它与li后代的p元素匹配,则可以将匹配更改为p//li

除此之外,您还可以拥有一个匹配p的模板,您首先只选择text()个节点,嵌入p标记,然后选择其他元素。< / p>

<xsl:template match="p">
    <p>
        <xsl:apply-templates select="text()" />            
    </p>
    <xsl:apply-templates select="*" />
</xsl:template>

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    <xsl:output method="html" indent="yes" />

    <xsl:strip-space elements="*" />

    <xsl:template match="p">
        <p>
            <xsl:apply-templates select="text()" />            
        </p>
        <xsl:apply-templates select="*" />
    </xsl:template>

    <xsl:template match="li">
        <p>
            <xsl:apply-templates/>
        </p>
    </xsl:template>

    <xsl:template match="text()">
        <xsl:value-of select="normalize-space()" />
    </xsl:template>
</xsl:stylesheet>

注意我在text()上添加了一个匹配以消除空格。

答案 2 :(得分:0)

这就是为什么&#34;玩耍&#34;并不是学习语言的最佳方式。您可能正在做的是阅读一些示例代码并构建自己的心理模型,以及它的工作方式 - 而且心智模型非常错误。最糟糕的是,一旦你掌握了它,就很难重新学习它。您需要获得一本关于XSLT的好书,并阅读基础概念。

您为自己创建的心理模型是样式表中的<p>是输出<p>开始标记的指令,而</p>是输出结束标记的指令。好吧,XSLT不输出标签,它将节点写入结果树,写元素节点是原子操作,它不能分成两个操作,每个操作写半个节点。因此,在样式表中,<p>(content)</p>是一条指令,它将p元素写入结果树,并评估(content)以生成该节点的内容。顺便说一句,这解释了为什么样式表必须是格式良好的XML。

有两种方法可以回答SO问题:&#34;这是怎么做的&#34;和&#34;这是你出错的地方&#34;。 @TimC给了你一个很好的&#34;怎么做&#34;回答所以我不会重复这一点,但我认为你也会受益于&#34;这是你出错的地方&#34;答案。