所以我的xml内容如下:
原始XML:
<p id="ACB1234" trackparabreak="true">
<t>
<apple>Some texts</apple>
<p trackparabreak="true">
<t> Some texts </t>
</p>
<orange>Some Texts</orange>
</t>
</p>
期望输出:
<p id="ACB1234" trackparabreak="true">
<t>
<apple>Some texts</apple>
</t>
</p>
<p trackparabreak="true">
<t> Some texts </t>
</p>
<p>
<t>
<orange> Some Texts </orange>
<t>
<p>
如何使用xslt-1.0获得所需的输出?
就像我在你的问题下面的评论中所说的,没有足够的信息来涵盖所有情况,但通过调整下面的XSLT,你可能可以实现你需要的。警告:黑客!todo:处理属性并规范化空间。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template match="/">
<root>
<xsl:apply-templates/>
</root>
</xsl:template>
<xsl:template match="p[not(ancestor::p)]">
<p>
<t>
<xsl:apply-templates select="t/apple"/>
</t>
</p>
<xsl:apply-templates select="t/*[not(self::apple)]"/>
</xsl:template>
<xsl:template match="apple">
<apple>
<xsl:apply-templates/>
</apple>
</xsl:template>
<xsl:template match="p[ancestor::p]">
<p>
<t>
<xsl:apply-templates/>
</t>
</p>
</xsl:template>
<xsl:template match="orange">
<p>
<t>
<orange>
<xsl:apply-templates/>
</orange>
</t>
</p>
</xsl:template>
</xsl:stylesheet>
输入:
<p id="ACB1234" trackparabreak="true">
<t>
<apple>APPLE TEXT</apple>
<p trackparabreak="true">
<t>PARA INSIDE TEXT</t>
</p>
<orange>ORANGE TEXT</orange>
</t>
</p>
输出:
<root>
<p>
<t>
<apple>APPLE TEXT</apple>
</t>
</p>
<p>
<t> PARA INSIDE TEXT </t>
</p>
<p>
<t>
<orange>ORANGE TEXT</orange>
</t>
</p>
</root>
尽管@Marcin猜测问题出在苹果和橙子身上,但我的猜测是,问题出在trackparabreak属性上。也许他是对的,我是错的,但你解释得太糟糕了,我们只能猜测。
这是一个棘手的问题,我不会把时间花在一个完整的解决方案上,部分原因是像这样的事情在XSLT2.0中要容易得多,我讨厌把一只手绑在背后工作,部分原因在于当需求不明确时,写很多代码是没有意义的。例如,我不知道你想对一个没有trackparabreak属性的<p>
做什么,因为你的例子中没有。
这类问题的常用技术是同级递归。这里的模型是,在父元素的模板规则中,将模板应用于第一个子元素(child::*[1]
),在子元素的模板法则中,在处理完子元素后,将模板应用于下一个同级元素(following-sibling::*[1]
);除非遇到中断条件,比如trackparabreak的存在,在这种情况下,停止同级递归并展开堆栈。