Сохранение каждого узла XML-документа в виде файла с XProc
Я получил документ XML со следующей структурой
<listOfNodes>
<node name="file1">content1</node>
<node name="file2">content2</node>
...
<node name="fileN">contentN</node>
</listOfNodes>
Я хочу создать конвейер xproc с результатом:
- file1.txt с контентом1
- file2.txt с контентом2
- ...
- fileN.txt с содержимым N
Мой первый подход:
<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 по этому вопросу.
Кто-нибудь может мне помочь, пожалуйста?
3 ответа
При условии, что 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
вместо.
Следующий конвейер выполняет свою работу:
<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>
Чтобы понять, почему ваш код выдавал ошибку, я попробовал это сам. Но не смог воспроизвести вашу ошибку. Это хорошо работает в 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, а также я добавил p: before interation-position(). Я удалил "file:/" по практической причине, что файлы записывались в корень моей файловой системы.
Я не смог найти записи об ошибке DX0006. Может быть, он попытался записать файлы в корне на вашем компьютере, но не позволил?
НТН!