所以我的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获得所需的输出?
答案 0 :(得分:0)
就像我在你的问题下面的评论中所说,没有足够的信息来涵盖所有情况,但通过调整下面的XSLT,你可以实现你所需要的。警告:hackery! 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>
答案 1 :(得分:0)
XSLT不会在串行输出文件中创建标记,而是在树中创建节点。创建元素节点是不可分割的操作,您不能在不同时间创建“节点的开始”和“节点的结束”作为独立的操作。因此,你的头脑中有一个错误的模型,关于处理的工作方式,这将使解决问题变得困难。
虽然@Marcin已经猜到问题是关于苹果和橘子,但我猜测它是关于trackparabreak的属性。也许他是对的,我错了,但你已经解释得太糟糕了,我们只能猜测。
这是一个棘手的问题,我不打算花时间在一个完整的解决方案上,部分原因是因为这样的事情在XSLT 2.0中变得如此简单,我讨厌用一只手绑在我背后的工作,部分是因为那里有当要求不明确时,没有必要编写大量代码。例如,我不知道你想要对没有trackparabreak属性的<p>
做什么,因为你的例子中没有。{/ p>
这类问题的常用技巧是兄弟递归。这里的模型是在父元素的模板规则中,您将模板应用于第一个子元素(child::*[1]
),并在子元素的模板规则中,在处理子元素后,将apply-templates应用于下一个兄弟(following-sibling::*[1]
);除非你遇到像trackparabreak这样的休息状态,在这种情况下你会停止兄弟的递归并展开堆栈。