这可能是一个新手问题,但是,我再说一遍: - )
我有以这种格式的XML文件:
<chapter>
<title>chapter title</title>
<para>p1</para>
<para>p2</para>
<para>p3</para>
<!-- ....and so on for a lot of para elements -->
</chapter>
...由像这样的XSL模板处理......
<xsl:template match="para">
<xsl:if test="count(following-sibling::para) = 1 and count(preceding-sibling::para) > 13">
<!-- Insert Some Stuff -->
</xsl:if>
</xsl:template>
这里的逻辑是:如果前面有足够的&lt; para&gt;,则在倒数第二个元素之前插入一些东西。兄弟姐妹。
此代码完成工作并正常工作。
现在,由于我无法控制的原因,我需要调整该模板以处理以下类型的文件......
<chapter>
<title>chapter title</title>
<para>p1</para>
<para>p2</para>
<para>p3</para>
<section>
<para>p4</para>
<para>p5</para>
</section>
<para>p6</para>
<section>
<title>section title</title>
</section>
<para>p7</para>
<section>
<para>p8</para>
</section>
<!-- ....and so on for a lot of para elements -->
</chapter>
与这些文件的区别在于&lt; section&gt;元素可以随机出现,有时包含&lt; para&gt;元素,有时不是。没有办法预测何时何地&lt; section&gt;元素将出现。
我需要原始的XSL模板以相同的方式使用这种格式,尽管&lt; section&gt;元素在那里。这意味着&lt; para&gt;即使他们有时是孩子,有时也是兄弟姐妹,他们仍然需要以相同的方式计算。
总之,我需要旧代码的逻辑像以前一样工作,好像它完全忽略了&lt; section&gt;的存在。元件。
原始模板&lt; xsl:if test =“...”&gt;应该是什么?被重写以使其成功?
性能不是问题 - 这些都是手动运行的临时转换。
仅限XSLT 1.0,
感谢。
答案 0 :(得分:1)
如果没有看到完整的样式表和预期的输出,很难回答你的问题。
不会:
<xsl:template match="para">
<xsl:if test="count(following::para) = 1 and count(preceding::para) > 13">
<!-- Insert Some Stuff -->
</xsl:if>
</xsl:template>
为你工作?
如果您确定您建议的内容应该适用于该示例 在问题中给出
嗯,问题中给出的示例没有所需的最小para
个节点 - 但是如果我们降低了阈值:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para">
<xsl:if test="count(following::para) = 1 and count(preceding::para) > 5">
<INSERTED_NODE/>
</xsl:if>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
测试输入A
<chapter>
<title>Section Title 1</title>
<para>Para 1</para>
<para>Para 2</para>
<para>Para 3</para>
<section>
<title>Section Title 2</title>
<para>Para 4</para>
<para>Para 5</para>
</section>
<para>Para 6</para>
<section>
<title>Section Title 3</title>
<para>Para 7</para>
<para>Para 8</para>
</section>
<para>Para 9</para>
<para>Para 10</para>
</chapter>
结果A
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title>Section Title 1</title>
<para>Para 1</para>
<para>Para 2</para>
<para>Para 3</para>
<section>
<title>Section Title 2</title>
<para>Para 4</para>
<para>Para 5</para>
</section>
<para>Para 6</para>
<section>
<title>Section Title 3</title>
<para>Para 7</para>
<para>Para 8</para>
</section>
<INSERTED_NODE/>
<para>Para 9</para>
<para>Para 10</para>
</chapter>
测试输入B
<chapter>
<title>Section Title 1</title>
<para>Para 1</para>
<para>Para 2</para>
<para>Para 3</para>
<section>
<title>Section Title 2</title>
<para>Para 4</para>
<para>Para 5</para>
</section>
<para>Para 6</para>
<section>
<title>Section Title 3</title>
<para>Para 7</para>
<para>Para 8</para>
</section>
<para>Para 9</para>
</chapter>
结果B
<?xml version="1.0" encoding="UTF-8"?>
<chapter>
<title>Section Title 1</title>
<para>Para 1</para>
<para>Para 2</para>
<para>Para 3</para>
<section>
<title>Section Title 2</title>
<para>Para 4</para>
<para>Para 5</para>
</section>
<para>Para 6</para>
<section>
<title>Section Title 3</title>
<para>Para 7</para>
<INSERTED_NODE/>
<para>Para 8</para>
</section>
<para>Para 9</para>
</chapter>
有没有办法强制每章元素插入一次?
是的,你可以这样做:
<xsl:template match="para">
<xsl:variable name="i">
<xsl:number count="para" from="chapter" level="any"/>
</xsl:variable>
<xsl:variable name="n" select="count(ancestor::chapter//para)" />
<xsl:if test="$i + 1 = $n and $n > 5">
<INSERTED_NODE/>
</xsl:if>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
更有效的解决方案是在章级别进行一次计数,并将其作为参数传递给参数。