How to make p:xslt aggregate input from two sources

白昼怎懂夜的黑 提交于 2019-12-13 03:23:37

问题


After reading the XProc question below:

XSLT with XProc - parameter binding in the required type

Passing document() parameter to an xslt in XProc pipeline

It seems impossible to pass document-node() type parameter to XSLT in XProc.

So the only way to workaround is: generate temporary file and pass the URL of temporary file as parameter to XSLT.

Look following example:

big-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>

final-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>

generate-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>

source-data.xml

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

My question is:

Is this solution has sequential nor synchronized problem?

Is there any new solution in 2018?

How to safe delete temporary file: temp-data.xml?

@grtjn


回答1:


My XProc knowledge is a bit rusty, but let me try to answer anyhow..

The issue with above code is that the final-calculation.xsl might try to read temp-data.xml before it is written to disk. You could get a not found error, an error stating you cannot write because it is being read elsewhere, or worst of all you could end up reading an old copy of the temp file in case you run repeatedly.

Your best bet is to use p:wrap-sequence with a p:input that pulls in two source streams by simply adding multiple references inside it. You then use that as primary input for you second xsl, in which you take the input back apart into the two pieces you need.

So instead of p:store something like (untested):

<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>

With this you should not need the temp-data param on your xsl anymore, and inside you just need to keep in mind that there is an extra wrapper element that you need to unwrap inside the xsl, and that the temp-data is the second child within that wrapper element.

HTH!




回答2:


After working a bit with XProc and seeing different solutions, I found now a way to implement this in XProc. It is a bit tricky, but it works:

<?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>

Please see the p:documentation elements for description, how it works.



来源:https://stackoverflow.com/questions/49011357/how-to-make-pxslt-aggregate-input-from-two-sources

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!