xslt展平和解开DocBook para元素

时间:2013-12-06 14:43:10

标签: xml xslt docbook

许多人在上一个问题上帮助我: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>

希望这会让事情更清楚。

感谢所有人的帮助。

拉​​斯

1 个答案:

答案 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>