我正在尝试根据后代元素的位置拆分元素树.(特别是,我正在尝试解析Adobe的IDML.)我希望能够转换一个看起来像这样的树:
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bar">
<Content>foo</Content>
<Br />
<Content>bar</Content>
</CharacterStyleRange>
<CharacterStyleRange style="bop">
<Content>baz</Content>
<Br />
<Hyperlink>
<Content>boo</Content>
<Br />
<Content>meep</Content>
</Hyperlink>
</ParagraphStyleRange>
Run Code Online (Sandbox Code Playgroud)
分裂树木:
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bar">
<Content>foo</Content>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bar">
<Content>bar</Content>
</CharacterStyleRange>
<CharacterStyleRange style="bop">
<Content>baz</Content>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bop">
<Hyperlink>
<Content>boo</Content>
</Hyperlink>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bop">
<Hyperlink>
<Content>meep</Content>
</Hyperlink>
</CharacterStyleRange>
</ParagraphStyleRange>
Run Code Online (Sandbox Code Playgroud)
然后我可以使用普通的XSL解析.(编辑:我最初<Br/>在原始位置显示标签,但是它们是否存在并不重要,因为它们包含的信息现在由分裂元素表示.我认为如果没有它们可能更容易解决这个问题担心让他们进入.)
我尝试使用xsl:for-each-groupXSLT 2.0规范(例如<xsl:for-each-group select="CharacterStyleRange/*" group-ending-with="Br">)中的建议,但我无法弄清楚如何在树的每个级别应用它(<Br />标签可以出现在任何级别,例如在<Hyperlink>元素内部的元素内<CharacterStyleRange>,并且它也限制我只有在所选深度应用的模板.
编辑:我的示例代码只显示树需要拆分的一个地方,但可以有任意数量的分割点(但总是相同的元素.)
编辑2:我添加了一些更详细的例子,以显示一些并发症.
这个XSLT 1.0(当然还有XSLT 2.0)转换:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="text()"/>
<xsl:template match="/">
<xsl:call-template name="Split">
<xsl:with-param name="pSplitters"
select="//Br"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="Split">
<xsl:param name="pSplitters"/>
<xsl:if test="$pSplitters">
<xsl:for-each select="$pSplitters[1]">
<xsl:call-template name="buildTree">
<xsl:with-param name="pLeafs" select=
"preceding-sibling::node()[not(descendant::Br)]"/>
</xsl:call-template>
<xsl:if test=
"not(following-sibling::node()//Br)">
<xsl:call-template name="buildTree">
<xsl:with-param name="pLeafs" select=
"following-sibling::node()"/>
</xsl:call-template>
</xsl:if>
<xsl:call-template name="Split">
<xsl:with-param name="pSplitters" select=
"$pSplitters[position() > 1]"/>
</xsl:call-template>
</xsl:for-each>
</xsl:if>
</xsl:template>
<xsl:template name="buildTree">
<xsl:param name="pAncestors" select="ancestor::*"/>
<xsl:param name="pLeafs"/>
<xsl:choose>
<xsl:when test="not($pAncestors)">
<xsl:copy-of select="$pLeafs"/>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="vtopAncestor" select="$pAncestors[1]"/>
<xsl:element name="{name($vtopAncestor)}"
namespace="{namespace-uri($vtopAncestor)}">
<xsl:copy-of select=
"$vtopAncestor/namespace::* | $vtopAncestor/@*"/>
<xsl:call-template name="buildTree">
<xsl:with-param name="pAncestors"
select="$pAncestors[position()>1]"/>
<xsl:with-param name="pLeafs" select="$pLeafs"/>
</xsl:call-template>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
当应用于提供的XML文档时:
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bar">
<Content>foo</Content>
<Br />
<Content>bar</Content>
</CharacterStyleRange>
<CharacterStyleRange style="bop">
<Content>baz</Content>
<Br />
<Hyperlink>
<Content>boo</Content>
<Br />
<Content>meep</Content>
</Hyperlink>
</CharacterStyleRange>
</ParagraphStyleRange>
Run Code Online (Sandbox Code Playgroud)
产生想要的,正确的结果:
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bar">
<Content>foo</Content>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bar">
<Content>bar</Content>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bop">
<Content>baz</Content>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bop">
<Hyperlink>
<Content>boo</Content>
</Hyperlink>
</CharacterStyleRange>
</ParagraphStyleRange>
<ParagraphStyleRange style="foo">
<CharacterStyleRange style="bop">
<Hyperlink>
<Content>meep</Content>
</Hyperlink>
</CharacterStyleRange>
</ParagraphStyleRange>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
977 次 |
| 最近记录: |