阅读下面的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
答案 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>