1

阅读下面的 XProc 问题后:

XSLT 与 XProc - 所需类型的参数绑定

将 document() 参数传递给 XProc 管道中的 xslt

在 XProc 中将 document-node() 类型参数传递给 XSLT 似乎是不可能的。

所以唯一的解决方法是:生成临时文件并将临时文件的 URL 作为参数传递给 XSLT。

看下面的例子:

大命令.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">
    <p:output port="result">
        <p:pipe port="result" step="final-calculation"/>
    </p:output>

    <p:xslt name="generate-temp-data" template-name="main">
        <p:input port="source">
            <p:empty/>
        </p:input>
        <p:input port="stylesheet">
            <p:document href="generate-temp-data.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>

    <p:store name="store-temp-data" href="temp-data.xml"/>

    <p:xslt name="final-calculation" >
        <p:input port="source">
            <p:document href="source-data.xml"/>
        </p:input>
        <p:input port="stylesheet">
            <p:document href="final-calculation.xsl"/>
        </p:input>
        <p:with-param name="temp-data" select="/">
            <p:pipe port="result" step="store-temp-data"/>
        </p:with-param>
    </p:xslt>
</p:declare-step>

最终计算.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:param name="temp-data"/>
    <xsl:variable name="temp-data-doc" select="doc($temp-data)"/>

    <xsl:template match="/">
        <final>
            <xsl:for-each select="$temp-data-doc//record">
                <xsl:value-of select="."/>
            </xsl:for-each>
        </final>
    </xsl:template>
</xsl:stylesheet>

生成临时数据.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:template name="main">
        <temp-data>
            <record>1</record>
            <record>2</record>
            <record>3</record>
        </temp-data>
    </xsl:template>
</xsl:stylesheet>

源数据.xml

<?xml version="1.0" encoding="UTF-8"?>
<x/>

我的问题是:

这个解决方案是否有顺序或同步问题?

2018年有什么新的解决方案吗?

如何安全删除临时文件:temp-data.xml?

@grtjn

4

3 回答 3

1

我的 XProc 知识有点生疏,但无论如何让我尝试回答..

上述代码的问题是 final-calculation.xsl 可能会在将 temp-data.xml 写入磁盘之前尝试读取它。您可能会收到一个未找到的错误,一个错误说明您无法写入,因为它正在其他地方被读取,或者最糟糕的是,如果您重复运行,您最终可能会读取临时文件的旧副本。

最好的办法是将 p:wrap-sequence 与 ap:input 一起使用,只需在其中添加多个引用即可拉入两个源流。然后,您将其用作第二个 xsl 的主要输入,在其中您将输入分成您需要的两部分。

因此,而不是 p:store 之类的东西(未经测试):

<p:wrap-sequence wrapper="wrapper">
  <p:input>
    <p:document href="source-data.xml"/>
    <p:pipe step="generate-temp-data" pipe="result"/>
  </p:input>
</p:wrap-sequence>

有了这个,你应该不再需要你的 xsl 上的 temp-data 参数了,在里面你只需要记住,有一个额外的包装元素需要在 xsl 中展开,并且 temp-data 是第二个该包装元素中的子元素。

于 2018-02-28T10:28:35.763 回答
1

p:xslt如果您使用 XSLT 2.0version="2.0"和然后在 XSLT 代码中您能够并且愿意访问该集合,我认为您可以将输入端口上的多个文档传递给该步骤:

<?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" xpath-version="2.0">
    <p:output port="result">
        <p:pipe port="result" step="final-calculation"/>
    </p:output>

    <p:xslt name="generate-temp-data" template-name="main">
        <p:input port="source">
            <p:empty/>
        </p:input>
        <p:input port="stylesheet">
            <p:document href="generate-temp-data.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>

    <p:xslt name="final-calculation" version="2.0">
        <p:input port="source">
            <p:document href="source-data.xml"/>
            <p:pipe port="result" step="generate-temp-data"/>
        </p:input>
        <p:input port="stylesheet">
            <p:document href="final-calculation.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>
</p:declare-step>



<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:variable name="temp-data-doc" select="collection()[2]"/>

    <xsl:template match="/">
        <final>
            <xsl:for-each select="$temp-data-doc//record">
                <xsl:value-of select="."/>
            </xsl:for-each>
        </final>
    </xsl:template>
</xsl:stylesheet>
于 2020-02-27T09:02:23.993 回答
0

在使用 XProc 并看到不同的解决方案后,我现在找到了一种在 XProc 中实现它的方法。这有点棘手,但它有效:

<?xml version="1.0" encoding="UTF-8"?>
<p:declare-step xmlns:p="http://www.w3.org/ns/xproc" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:c="http://www.w3.org/ns/xproc-step" version="1.0">
    <p:output port="result">
        <p:pipe port="result" step="final-calculation"/>
    </p:output>

    <p:xslt name="generate-temp-data" template-name="main">
        <p:input port="source">
            <p:empty/>
        </p:input>
        <p:input port="stylesheet">
            <p:document href="generate-temp-data.xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>
    <p:documentation>Create an empty temporary stylesheet which imports the final-calculation and has a parameter $temp-data-doc:</p:documentation>
    <p:identity>
        <p:input port="source">
            <p:inline>
                <xsl:stylesheet version="2.0">
                    <xsl:import href="final-calculation.xsl"/>
                    <xsl:param name="temp-data-doc" as="document-node()">
                        <xsl:document/>
                    </xsl:param>
                </xsl:stylesheet>
            </p:inline>
        </p:input>
    </p:identity>

    <p:documentation>Insert the temporary document as default value of the $temp-data-doc parameter:</p:documentation>
    <p:insert match="xsl:param[@name = 'temp-data-doc']/xsl:document" position="first-child" name="final-calculation-xsl">
        <p:input port="insertion">
            <p:pipe port="result" step="generate-temp-data"/>
        </p:input>
    </p:insert>

    <p:xslt name="final-calculation" >
        <p:input port="source">
            <p:document href="source-data.xml"/>
        </p:input>
        <p:documentation>Use the temporary stylesheet, not that from file system.</p:documentation>
        <p:input port="stylesheet">
            <p:pipe port="result" step="final-calculation-xsl"/>
        </p:input>
        <p:input port="parameters">
            <p:empty/>
        </p:input>
    </p:xslt>
</p:declare-step>

请参阅p:documentation描述的元素,它是如何工作的。

于 2018-11-13T17:48:40.383 回答