如何从两个来源

时间:2018-02-27 14:44:52

标签: xproc

阅读下面的XProc问题后:

XSLT with XProc - parameter binding in the required type

Passing document() parameter to an xslt in XProc pipeline

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

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

看下面的例子:

大command.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>

最终calculation.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>

生成-TEMP-data.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>

源data.xml中

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

我的问题是:

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

2018年有新的解决方案吗?

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

@grtjn

3 个答案:

答案 0 :(得分:1)

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

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

最好的办法是使用p:wrap-sequence和p:输入,只需在其中添加多个引用即可引入两个源流。然后使用它作为第二个xsl的主要输入,在这个输入中你将输入分成两部分。

所以代替p:存储类似(未经测试)的东西:

<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上的临时数据参数了,在内部你只需要记住,你需要在xsl内部展开一个额外的包装元素,以及临时数据是该包装元素中的第二个子节点。

HTH!

答案 1 :(得分: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元素以获取描述及其工作原理。

答案 2 :(得分:0)

我认为,如果您将XSLT 2.0与p:xslt一起使用,那么您可以在输入端口上将多个文档传递到version="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>