许多人在上一个问题上帮助我:xslt flattening out child elements in a DocBook para element
这个问题还有一个问题,我想看看之前是否有人这样做过。回顾之前的示例文本。之前的问题得到解答,解决了在块元素之间使用文本并用para元素包装它们的问题,因为我们的模式不像para元素中的tabe,figure等块元素。
<para>some text.....
<literallayout>
</literallayout>
more text....
<table>
...
</table>
even more text
<table>...</table>
<literallayout>text also look here</literlayout>
more text <link xlink:href="http://someurl.com">
</para>
这里的皱纹是内联元素,如链接,那些元素需要在para元素中。因此理想情况下最后两行文字应如下所示:
<para>more text <link xlink:hred="http://someurl.com">someurl</link></para>
使用for-each构造,我可以遍历para元素中的节点,但是如果任何节点是非块元素,我将必须将它们包装在para元素中。如果在此非块元素之前和/或之后存在文本节点,则希望将所有这些都包含在para元素中。
我可以想到如何以任何其他编程语言的方式执行此操作,但是需要XSLT专家的帮助才能启发我这样做的优雅方式!
有人要求提供更多信息。在上面的示例中,我需要能够输出以下内容:
<para>some text..... </para>
<literallayout>
</literallayout>
<para> more text.... </para>
<table> ... </table>
<para> even more text </para>
<table>...</table>
<literallayout>
<para>more text <link xlink:hred="http://someurl.com">someurl</link></para>
希望这会让事情更清楚。
感谢所有人的帮助。
拉斯
答案 0 :(得分:1)
这是一个经典问题。就我而言,扁平化通常通过XSLT分组来解决。当然,当您必须使用基于递归的算法来实现它时,使用XSLT 1实现起来并不容易。但让我们考虑一个更简单的解决方案(XSLT 2):
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:f="http://stackoverflow.com/xslt-functions"
xmlns:doc="http://docbook.org/ns/docbook"
xmlns="http://docbook.org/ns/docbook"
exclude-result-prefixes="#all">
<xsl:variable name="block-elements" select="QName('http://docbook.org/ns/docbook', 'table'),
QName('http://docbook.org/ns/docbook', 'figure')"/>
<xsl:template match="doc:para">
<xsl:for-each-group select="node()" group-adjacent="f:is-block-level-element(.)">
<xsl:choose>
<!-- If current node is a block element process the node as is -->
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<!-- Otherwise, wrap it in para element -->
<xsl:otherwise>
<para>
<xsl:apply-templates select="current-group()"/>
</para>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
<xsl:function name="f:is-block-level-element" as="xs:boolean">
<xsl:param name="node" as="node()"/>
<xsl:sequence select="$node instance of element() and
node-name($node) = $block-elements"/>
</xsl:function>
<xsl:template match="attribute() | node()">
<xsl:copy>
<xsl:apply-templates select="attribute() | node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
目标内容为:
<section xmlns="http://docbook.org/ns/docbook">
<para>some text.....
<literallayout>
</literallayout>
more text....
</para>
<table>
...
</table>
<para>
even more text
</para>
<table>...</table>
<para>
<literallayout>text also look here</literallayout>
more text
<link/>
</para>
</section>