使用 xsl 将单个 XML 文档转换为多个文档

发布于 2024-09-18 15:01:23 字数 336 浏览 3 评论 0原文

给定以下 xml 文档:

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

我希望使用 xsl 转换来生成 2 个 XML 文档:

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

这可能吗

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

Given the following xml document:

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

I was hoping to use an xsl transform to generate 2 XML documents:

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

And

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

Is this possible?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

姐不稀罕 2024-09-25 15:01:23

在 XSLT 1.0 中,不可能创建多于一棵树作为任何转换的输出,但在 XSLT 2.0 中,这可以非常容易地完成。

在 XSLT 1.0 中,可以使用 < /code>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

In XSLT 1.0 it isn't possible to create more than one tree as the output of any transformation, but in XSLT 2.0 this can be done really easy.

In XSLT 1.0 one could use the <exsl:document> extension element of EXSLT.

Or, one can have a transformation, that is provided a global (and externally specified) parameter, containing the element name of the element that must be extracted into a single document:

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

when applied on this XML document (based on the provided one):

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

the wanted result is produced:

<doc1>
  Doc 1 Content
</doc1>

And you will run this transformation once for every element, whose sub-tree should be extracted into a separate document.


Here is an XSLT 2.0 solution:

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

When this transformation is applied on the following XML document (based on the provided one):

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

The result is correctly output to three documents:

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
小糖芽 2024-09-25 15:01:23

我们曾经遇到过这个问题,并通过稍微作弊解决了它:

第一步:创建一个大文件,其中包含由程序指令或注释分隔的不同 xml 脚本。
步骤2:使用程序将文件剪切成单独的文件。

请注意,您的中间结果是无效的 xml,但最终结果是有效的。

示例

<doc1>..<doc1>
<!-- SEP -->
<doc2>..<doc2>
<!-- SEP -->
<doc3>..<doc3>

We had that problem once and solved it by slightly cheating:

step 1: create one big file containing different xml scripts separated by program instructions or comments.
step 2: use a program to cut the file into separate files.

Note that your intermediate result is invalid xml, but the end result is valid.

Example

<doc1>..<doc1>
<!-- SEP -->
<doc2>..<doc2>
<!-- SEP -->
<doc3>..<doc3>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文