匹配动态xslt模板

时间:2012-06-14 15:08:07

标签: xml xslt matching

好的,所以我有一个我似乎无法解决的xslt问题。这是我第二次尝试提出问题,请不要将其标记为重复。

我的问题是,我希望在文档中的第四个<p>标记之后添加一些HTML。问题是可能有<p>个标记,其属性为class="exclude"

如果<p>标记有该类,我不想渲染该段落。与此同时,我仍然希望在第4段之后渲染我包含的html,无论<p class="excludes"的数量是多少

EDIT :: 这是我以前的xsl。这会将我包含的html插入第4段。

<xsl:template match="content/p[position() = 4]">
     content include<xsl:apply-templates /></p>
</xsl:template> 

以下是一些示例输入/输出

首先是基本示例,其中没有<p class="excludes">我的输入是:

<body>
<p></p>
<p></p>
<p></p>
<p></p>
include new HTML here
<p></p>
...
</body>

在该示例中,html在通过我的xslt后第4段后很好地呈现。

但是,我需要考虑<p class="exclude">

以下是<p class="exclude" being used >

的更复杂的示例
<body>
<p class="exclude"></p> (should not be rendering on page)
<p></p>
<p></p>
<p></p>
<p></p>
include new HTML here
<p></p>
...
</body>

请注意,在此示例中,包含的HTML出现在第5个*段之后,因为第一个段落不应该在页面上呈现,但同时我希望呈现的HTML包含在第4个呈现的段落之后。让我们再看一个更复杂的例子。

<body>
<p class="exclude"></p> (this should not be rendering on page)
<p></p>
<p class="exclude"></p> (this should not be rendering on page)
<p class="exclude"></p> ...
<p></p>
<p class="exclude"></p> ...
<p></p>
<p class="exclude"></p> ...
<p class="exclude"></p> ...
<p class="exclude"></p> ...
<p></p>
new HTML include here
<p></p>
...
<body>
<p class="exclude"></p>

现在,在我的最后一个示例中,您可以看到已添加多个<p class="excludes",是的,我仍然希望在第4个渲染段落之后渲染新的html内容,或者在此示例中,所有段落的第11个总计。

如果有人有任何xslt可以帮助我实现这一点,这将是伟大的。请记住我正在使用xslt 1.0提前致谢

2 个答案:

答案 0 :(得分:1)

这是另一个XSLT 1.0样式表选项。

在这篇文章中,我试图考虑评论中提到的p元素的“正常处理”。

在示例中,我添加了一条处理指令,仅用于显示已处理p。这可以替换或删除,具体取决于您在XSLT中执行的操作。

XML输入

<body>
    <p class="exclude">delete1</p>
    <p>keep1</p>
    <p class="exclude">delete2</p>
    <p class="exclude">delete3</p>
    <p>keep2</p>
    <p class="exclude">delete4</p>
    <p>keep3</p>
    <p class="exclude">delete5</p>
    <p class="exclude">delete6</p>
    <p class="exclude">delete7</p>
    <p>keep4</p>
    <p>keep5</p>
    <p class="exclude">delete8</p>
</body>

XSLT 1.0 (使用Xalan和Saxon 6.5.5测试)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <!--Strip p if class attribute value is exclude.-->
    <xsl:template match="p[@class='exclude']"/>

    <!--Special handling of the 4th non-exclude p. Call the "normal" template to 
        handle any other p processing and then output the additional HTML.-->
    <xsl:template match="p[not(@class='exclude')][count(preceding::p[not(@class='exclude')])+1=4]">
        <xsl:call-template name="normal"/>      
        <b>ADDITIONAL HTML HERE</b>
    </xsl:template>

    <!--This is the "normal" processing of "p". For the example, just adding a PI.-->
    <xsl:template match="p" name="normal">
        <xsl:copy>
            <xsl:processing-instruction name="processed">normally</xsl:processing-instruction>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>     
    </xsl:template>

</xsl:stylesheet>

<强>输出

<body>
   <p><?processed normally?>keep1</p>
   <p><?processed normally?>keep2</p>
   <p><?processed normally?>keep3</p>
   <p><?processed normally?>keep4</p>
   <b>ADDITIONAL HTML HERE</b>
   <p><?processed normally?>keep5</p>
</body>

答案 1 :(得分:0)

对于您正在处理的每个p,请检查......

<xsl:if test="count(preceding::p[not(@class='exclude')])=4">
   render your html here
</xsl:if>

修改

另外还有一个问题:

<xsl:apply-tempates select="p[not(@class='exlude')]"/>

<xsl:template match="p">
   <p>
     <xsl:if test="count(preceding::p[not(@class='exclude')])=4">
      render your html here
   </xsl:if>
   </p>
</xsl:template>

如果你不想要所有其他的p,你可以把数字放在比赛中。

修改

我已经查看了你的更新问题,我不确定它是如何工作的,因为你有一个不平衡的模板(你有一个结束p而不是一个开放的?) - 我认为这是一个错字。你也说你的p在体内,但你在内容/ p上匹配。内容标记来自何处。

无论如何,通过更正,假设您的原始模板是:

<xsl:template match="content/p[position() = 4]">
    <p>content include<xsl:apply-templates /></p> 
</xsl:template> 

并且有效,只需将其更改为

即可

只需将其更改为

<xsl:template match="p[count(preceding::p[not(@class='exclude')])=4]">
    <p>content include<xsl:apply-templates /></p> 
</xsl:template> 

这会给你正确的东西