【问题标题】:xslt flattening and unflattening DocBook para elementxslt 扁平化和非扁平化 DocBook para 元素
【发布时间】:2013-12-06 14:43:09
【问题描述】:

你们中的许多人在上一个问题上帮助我: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 元素中。所以最后两行文字 about 理想情况下应该是这样的:

<para>more text <link xlink:hred="http://someurl.com">someurl</link></para>

使用 for-each 构造,我可以遍历 para 元素中的节点,但如果任何节点是非块元素,我将不得不将它们包装在 para 元素中。如果在这个非块元素之前和/或之后有一个文本节点,那么最好将所有这些都包装在一个 para 元素中。

我可以想到如何使用任何其他编程语言来做到这一点,尽管是以一种 hacky 的方式,但需要 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>

希望这能让事情更清楚。

感谢大家的帮助。

罗斯

【问题讨论】:

  • 你能澄清一下吗?在您的示例中,link 元素已经在 para 元素中,即启动示例文档的元素。
  • 当然,让我稍微更新一下示例。

标签: xml xslt docbook


【解决方案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>

【讨论】:

  • 我将不得不绕开这个,但它看起来不错!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多