1

我得到了一个具有以下结构的 xml 文档

<listOfNodes>
    <node name="file1">content1</node>
    <node name="file2">content2</node>
    ...
    <node name="fileN">contentN</node>
</listOfNodes>

我想用结果创建一个 xproc 管道:

  • file1.txt 与 content1
  • file2.txt 与 content2
  • ...
  • fileN.txt 与 contentN

我的第一种方法是:

<p:declare-step name="step_1" type="ts:Extract">
        <p:input port="source" />
        <p:filter select="nodes" name="step_1.1" />
         <p:for-each name="step_1.2">
            <p:iteration-source><p:pipe port="result" step="step_1.1"/></p:iteration-source>
            <p:store method="text" >
                 <p:with-option name="href" select="concat('file:/', 'step_1_',iteration-position(),'.txt')"/>
            </p:store>
        </p:for-each>
</p:declare-step>

但是我得到了一个 DX0006 错误。

有人可以帮我吗?

4

3 回答 3

2

如果 content1, ..., contentN 是格式良好的 XML,则以下管道可以解决问题:

<p:declare-step version="1.0" xmlns:p="http://www.w3.org/ns/xproc">
  <p:input port="source"/>
  <p:for-each>
    <p:iteration-source select="/*/node"/>
    <p:variable name="filename" select="concat(/node/@name, '.txt')"/>
    <p:unwrap match="/*"/>
    <p:store>
      <p:with-option name="href" select="$filename"/>
    </p:store>
  </p:for-each>
</p:declare-step>

如果 content1, ..., contentN 不是蠕虫良好的 XML(纯文本、多个同级元素等),那么您可以在应用之前将它们包装在 XML 包装器元素中p:store(或者干脆不应用该p:unwrap步骤)。如果您不想使用包装器元素,那么标准p:store将不起作用(某些 XProc 实现可能支持扩展属性p:store以仅存储文档元素的内容;但这是另一回事)。一种可能性是p:xslt改用。

于 2014-03-19T16:24:35.417 回答
1

以下 Pipeline 完成了这项工作:

<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" />
    <p:xslt name="create-document">
        <p:input port="source" />
        <p:input port="stylesheet">
            <p:document href="splitter.xsl" />
        </p:input>
        <p:input port="parameters"><p:empty/></p:input>
    </p:xslt>
    <p:for-each>
        <p:iteration-source>
            <p:pipe step="create-document" port="secondary" />
        </p:iteration-source>
            <p:store>
                <p:with-option name="method" select="'xml'" />
                <p:with-option name="href" select="p:base-uri(/*)" />
            </p:store>
        </p:for-each>

<p:sink>
    <p:input port="source"><p:pipe port="result" step="create-document"/></p:input>
</p:sink>
</p:declare-step>

但我还必须在 xslt 文件中拆分文件:

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

    <xsl:template match="node">
        <xsl:variable name="filename" select="concat(@name,'.txt')" />
        <saveTo><xsl:value-of select="$filename" /></saveTo>
        <xsl:result-document href="{$filename}">
            <node><xsl:value-of select="current()" /></node>
        </xsl:result-document>
    </xsl:template>

    <!-- standard copy template -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*"/>
            <xsl:apply-templates/>
        </xsl:copy>
    </xsl:template> 
</xsl:stylesheet>
于 2014-03-17T15:46:54.563 回答
0

只是为了了解您的代码为什么会抛出错误,我自己尝试过。但无法重现您的错误。这在 XMLCalabash 中运行得很好:

<p:declare-step name="step_1" type="ts:Extract" version="1.0" xmlns:p="http://www.w3.org/ns/xproc" xmlns:ts="ts">
    <p:input port="source" />
    <p:filter select="/*/node" name="step_1.1" />
     <p:for-each name="step_1.2">
        <p:iteration-source><p:pipe port="result" step="step_1.1"/></p:iteration-source>
        <p:store method="text" >
             <p:with-option name="href" select="concat('step_1_', p:iteration-position(), '.txt')"/>
        </p:store>
    </p:for-each>
</p:declare-step>

请注意,我必须添加 p 和 ts 命名空间声明,并且我还在 interation-position() 之前添加了 p:。我删除了 'file:/' 的实际原因是文件被写入我的文件系统的根目录。

我找不到 DX0006 错误的记录。也许它也尝试在您的机器上的根目录中写入文件,但不允许这样做?

于 2014-03-27T21:18:21.547 回答