Xml XProc:具有中间文件的多个XSLT转换

Xml XProc:具有中间文件的多个XSLT转换,xml,xproc,Xml,Xproc,我需要对中间XML文件进行几个XSLT转换。(我需要这些文件,因为后面的步骤会加载中间文件,所以实际情况有点棘手) 我想创建一个XProc pipleline。我试图编写以下代码,但这给了我一个错误: SCHWERWIEGEND: runxslt.xpl:26:44:err:XD0011:Could not read: intermediate.xml 17.05.2012 15:15:35 com.xmlcalabash.drivers.Main error SCHWERWIEGEND: I

我需要对中间XML文件进行几个XSLT转换。(我需要这些文件,因为后面的步骤会加载中间文件,所以实际情况有点棘手)

我想创建一个XProc pipleline。我试图编写以下代码,但这给了我一个错误:

SCHWERWIEGEND: runxslt.xpl:26:44:err:XD0011:Could not read: intermediate.xml 
17.05.2012 15:15:35 com.xmlcalabash.drivers.Main error
SCHWERWIEGEND: It is a dynamic error if the resource referenced by a p:document element does not exist, cannot be accessed, or is not a well-formed XML document.
17.05.2012 15:15:35 com.xmlcalabash.drivers.Main error
SCHWERWIEGEND: Underlying exception: net.sf.saxon.s9api.SaxonApiException: I/O error reported by XML parser processing file:/<somepath>/intermediate.xml:
/<somepath>/intermediate.xml (No such file or directory)
为了完整起见:以下是转换文件:

source.xml:

<root>
  <element name="A" />
</root>

first.xsl:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">
  <xsl:output indent="yes"/>

  <xsl:template match="root">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>
  <xsl:template match="element">
    <intermediate name="A" />
  </xsl:template>

</xsl:stylesheet>

final.xsl:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">
  <xsl:output indent="yes"/>

  <xsl:template match="root">
    <root>
      <xsl:apply-templates/>
    </root>
  </xsl:template>
  <xsl:template match="intermediate">
    <final name="A" />
  </xsl:template>

</xsl:stylesheet>

下面是一个关于实际应用程序的注释(当然,上面是一个简化)

  • 第一步:将源代码转换为更适合我处理的内容。输出:
    companys.xml
  • 获取步骤1的输出,并从中创建一个索引文件(
    index.xml
    )。索引文件必须可以手动编辑
  • 第三步是合并步骤1和步骤2创建的文件,并创建最终的xml(
    final.xml
  • 索引文件必须写入磁盘,并且我必须能够自己运行最后一步(这是一个不同的问题-我会为此编写不同的管道)


    companys.xml的输出(步骤1)是可选的,可以保存在内存中(但可能会变大)。

    我不太清楚为什么XMLCalabash在这里不起作用。我认为逻辑原则上应该是可行的,但显然XMLCalabash推迟了将文件写入磁盘的时间,直到稍后,甚至可能直到最后。不知道为什么

    但有一个优雅的解决方案,因为在继续处理之前,不需要存储中间结果。事实上,最好不要使用硬编码加载和存储。相反,请使用以下方法:

    <?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:input port="source" sequence="true"/> 
      <p:input port="parameters" kind="parameter"/>
      <p:output port="result" sequence="true"/> 
    
      <p:xslt name="first-to-intermediate"> 
        <p:input port="stylesheet"> 
          <p:document href="first.xsl"/> 
        </p:input> 
      </p:xslt> 
    
      <p:xslt> 
        <p:input port="stylesheet"> 
          <p:document href="final.xsl"/> 
        </p:input> 
      </p:xslt> 
    
    </p:declare-step> 
    
    使用-i,您可以将输入源绑定到输入文件,但是从脚本外部绑定,因此不需要硬编码。与-o类似,您可以将输出重定向到目标文件

    我还向代码中添加了一个“参数”输入,它会自动连接到p:xslt的输入。这样,您就不需要指定那些p:empty。它还允许将参数值从命令行传递到那些xslt中

    因为我删除了p:store,所以第二个p:xslt的“源”输入也不是必需的。默认情况下,第一个p:xslt的结果直接进入以下步骤的(主要)源输入

    --编辑--

    为了详细说明我自己的意见,您可以执行一个p:store并重复使用第一个p:xslt的输出两次,而无需从磁盘加载中间文档。您可以这样做:

    java -jar Calabash.jar -i source=first.xml -o result=final.xml runxslt.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:input port="source" sequence="false"/> 
      <p:input port="parameters" kind="parameter"/>
      <p:output port="result" sequence="false"/> 
    
      <p:xslt name="first-to-intermediate"> 
        <p:input port="stylesheet"> 
          <p:document href="first.xsl"/> 
        </p:input> 
      </p:xslt> 
    
      <p:store href="intermediate.xml"/>
    
      <p:xslt> 
        <p:input port="source"> 
          <p:pipe step="first-to-intermediate" port="result"/> 
        </p:input> 
        <p:input port="stylesheet"> 
          <p:document href="final.xsl"/> 
        </p:input> 
      </p:xslt> 
    
    </p:declare-step> 
    
    
    
    注意,我将declare步骤的输入和输出的sequence=true都更改为false。存储中间结果序列需要格外小心。这应该可以防止错误


    在我的例子中,我需要中间XML文件。我的问题不清楚,我道歉。我会编辑的。@patrick你能详细说明你在哪里使用它们吗?您可以使用p:log存储中间结果以进行调试,也可以在p:xslt之间执行p:store操作,但不要读取存储的文件,而是在第二个p:xslt的输入中使用p:port来引用第一个p:xslt的输出。您可以根据自己的喜好将任意多个步骤的输入绑定到单个其他步骤的结果。在文档末尾完成。我能清楚地表达自己吗?如果没有,我就试着找更好的词。好了,现在我明白了。诀窍是将第二个XSLT转换的输入连接到第一步的输出,而不是文件,因此这些转换的顺序很重要,XProc处理器不会优化任何东西。多谢各位@patrick:除了xproc邮件列表上所说的:诀窍在于,只要步骤有主要输入和输出,它们就会自动连接。p:store没有主输出,因此必须显式地为第二个p:xslt指定输入。但是,您可以轻松地直接连接到其他输出端口,而不是加载文件(需要稳定的执行顺序)。您会注意到,您甚至可以指向在该步骤之后编写的步骤的输出。只要它不是圆形的,它就应该工作。。
    java -jar Calabash.jar -i source=first.xml -o result=final.xml runxslt.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:input port="source" sequence="false"/> 
      <p:input port="parameters" kind="parameter"/>
      <p:output port="result" sequence="false"/> 
    
      <p:xslt name="first-to-intermediate"> 
        <p:input port="stylesheet"> 
          <p:document href="first.xsl"/> 
        </p:input> 
      </p:xslt> 
    
      <p:store href="intermediate.xml"/>
    
      <p:xslt> 
        <p:input port="source"> 
          <p:pipe step="first-to-intermediate" port="result"/> 
        </p:input> 
        <p:input port="stylesheet"> 
          <p:document href="final.xsl"/> 
        </p:input> 
      </p:xslt> 
    
    </p:declare-step>