Использование xsl для преобразования одного документа XML в несколько документов - PullRequest
2 голосов
/ 12 сентября 2010

Учитывая следующий XML-документ:

<XML>
<doc1>
</doc1>
<doc2>
</doc2>
<XML>

Я надеялся использовать преобразование xsl для генерации 2 XML-документов:

<XML>
<doc1>
</doc1>
<XML>

И

<XML>
</doc2>
<doc2>
<XML>

Возможно ли это?

Ответы [ 2 ]

3 голосов
/ 13 сентября 2010

В XSLT 1.0 невозможно создать более одного дерева в качестве результата любого преобразования , но в XSLT 2.0 это можно сделать очень просто.

В XSLT 1.0 можно использовать элемент расширения <exsl:document> EXSLT.

Или можно преобразовать, предоставив глобальный (и указанный снаружи) параметр, содержащий имя элемента, который должен быть извлечен в один документ:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pDocElement" select="'doc1'"/>

 <xsl:template match="/*/*">
  <xsl:if test="name()=$pDocElement">
   <xsl:apply-templates select="." mode="copy"/>
  </xsl:if>
 </xsl:template>

 <xsl:template match="node()" mode="copy">
  <xsl:copy-of select="."/>
 </xsl:template>

 <xsl:template match="text()"/>
</xsl:stylesheet>

при применении к этому документу XML (на основе предоставленного):

<t>
    <doc1>
  Doc 1 Content
    </doc1>
    <doc2>
  Doc 2 Content
    </doc2>
    <doc3>
  Doc 3 Content
    </doc3>
</t>

желаемый результат получен :

<doc1>
  Doc 1 Content
</doc1>

И вы выполните это преобразование один раз для каждого элемента, чье поддерево должно быть извлечено в отдельный документ .


Вот решение XSLT 2.0 :

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="node()|@*" mode="copy">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="/*/*[starts-with(name(),'doc')]">
  <xsl:result-document href="{name()}.xml">
   <xsl:apply-templates select="." mode="copy"/>
  </xsl:result-document>
 </xsl:template>

 <xsl:template match="/*">
  <xsl:apply-templates/>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к следующему документу XML (на основе предоставленного):

<t>
    <doc1>
  Doc 1 Content
    </doc1>
    <doc2>
  Doc 2 Content
    </doc2>
    <doc3>
  Doc 3 Content
    </doc3>
</t>

Результат корректно выводится на три документа :

Saxon 9.1.0.5J from Saxonica
Java version 1.6.0_21
Stylesheet compilation time: 868 milliseconds
Loading net.sf.saxon.event.MessageEmitter
Writing to file:/C:/Program%20Files/Java/jre6/bin/doc1.xml
Writing to file:/C:/Program%20Files/Java/jre6/bin/doc2.xml
Writing to file:/C:/Program%20Files/Java/jre6/bin/doc3.xml
Execution time: 151 milliseconds
Memory used: 11467936
NamePool contents: 18 entries in 18 chains. 6 prefixes, 6 URIs
0 голосов
/ 12 сентября 2010

Однажды у нас возникла эта проблема, и мы ее слегка обманули:

шаг 1: создайте один большой файл, содержащий различные сценарии xml, разделенные инструкциями или комментариями программы.шаг 2: используйте программу, чтобы разрезать файл на отдельные файлы.

Обратите внимание, что ваш промежуточный результат является недействительным xml, но конечный результат действителен.

Пример

<doc1>..<doc1>
<!-- SEP -->
<doc2>..<doc2>
<!-- SEP -->
<doc3>..<doc3>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...