1

要求: 是在输出xml上添加正确的Doctype声明【输入xml的根元素可以是champlesection元素】

输入 XML:chapter.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "docbookx.dtd">
<chapter>
    <title>Chapter Template Title</title>
    <para>Text</para>
    <section>
        <title>Section Title</title>
        <para>Section text</para>
    </section>
</chapter>

XSLT 文件:test.xsl:

  1. 样式表只是将输入 xml 复制到输出并在所有元素上添加 @sec
  2. 样式表将正确的 doctype 声明添加到输出 xml,因为输入 xml 根元素可以是 <chapter> 或 <section> 元素

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
    
    <xsl:template name="add-doctype-declaration">
        <xsl:choose>
            <xsl:when test="/chapter">
                <xsl:text disable-output-escaping="yes">
    &lt;!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "docbookx.dtd"&gt;
    </xsl:text>
            </xsl:when>
            <xsl:when test="/section">
                <xsl:text disable-output-escaping="yes">
    &lt;!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "docbookx.dtd"&gt;
    </xsl:text>
            </xsl:when>
        </xsl:choose>
    </xsl:template>
    
    <xsl:template match="/">
        <xsl:call-template name="add-doctype-declaration"/>
        <xsl:apply-templates/>
    </xsl:template>
    
    <!-- Identity Template -->
    <xsl:template match="@*|*|processing-instruction()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="section">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:attribute name="sec">
                <xsl:number/>
            </xsl:attribute>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template>
    
    </xsl:stylesheet>
    

预期输出.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "docbookx.dtd">
<chapter>
    <title>Chapter Template Title</title>
    <para>Text</para>
    <section sec="1">
        <title>Section Title</title>
        <para>Section text</para>
    </section>
</chapter>

使用任何 XSLT 引擎,转换工作都非常好,并且能够获得预期的输出

但是,如果转换是通过 XProc 完成的,我最终会出现以下错误。有人可以帮助解决此错误吗

err:XD0001 : XD0001 如果非 XML 资源在步骤输出中生成或到达步骤输入,则为动态错误。

XProc 文件:test.xpl

<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc"
    xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0" name="testing">
    <p:input port="source">
       <p:document href="chapter.xml"/>
    </p:input>
    <p:output port="result">
        <p:empty/>
    </p:output>

    <p:xslt version="1.0" name="transform">
        <p:input port="stylesheet">
            <p:document href="test.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>

    <p:store omit-xml-declaration="false" encoding="utf-8" name="serialize">
        <p:with-option name="href" select="output.xml"/>
    </p:store>

</p:declare-step>
4

2 回答 2

1

这是两个简单的示例,表明您不需要将 Doctype 生成上下文化

http://www.sharexml.com/x/get?k=uWn0KA7RThnt

章节http://www.sharexml.com/x/get?k=wAJlbUJfzIYQ

希望这可以帮助

[回答后更新]

如果您希望该文档类型动态更改

http://www.sharexml.com/x/get?k=pBAwCds86RnQ

http://www.sharexml.com/x/get?k=JHEWghzgWIq1

希望这可以帮助

于 2013-03-21T00:01:20.940 回答
0

这里的问题是您在此处创建的文档类型作为 XSLT 步骤结果的一部分传递给 XProc 引擎。但是,它是作为根元素之外的字符数据传递的。XProc 不允许这样做。

方法实际上有两个问题:

  • 不要使用 disable-output-escaping 除非你不能做任何其他事情。该xsl:output指令具有创建所需文档类型的完美方法,只需为其添加一个 public-doctype 和 system-doctype 属性。
  • XSLT 的输出选项将被忽略,因为结果实际上不是由 XSLT 引擎序列化,而是由 XPRoc。因此,您必须将这些 doctype 属性放在p:store步骤上,以使其在 XProc 中工作。

于 2013-03-19T06:29:19.127 回答