0

我们需要从具有未知数量的“info”元素的单个 XML 文档制作多个 XML 文档,每个文档都有一个“info”元素。例如,这个文档:

<alert>
  <identifier>2.49.0.1.124.76fea972.2015</identifier>  
  <info>
    <language>en</language>
  </info>
  <info>
    <language>fr</language>
  </info>
</alert>

应该产生这两个文件:

<alert>
  <identifier>2.49.0.1.124.76fea972.2015</identifier>  
  <info>
    <language>en</language>
  </info>
</alert>

<alert>
  <identifier>2.49.0.1.124.76fea972.2015</identifier>  
  <info>
    <language>fr</language>
  </info>
</alert>

在修剪“info”元素的兄弟姐妹时,我们需要复制所有祖先(到根)的所有节点、属性、命名空间等,以及特定“info”元素的所有节点、属性、命名空间等。

我是 XSLT 的新手,不知道如何做到这一点。任何帮助将不胜感激!

4

3 回答 3

1

在xsh中很容易:

my $orig := open file.xml ;
for my $info in /alert/info {
    my $clone := clone $orig ;
    my $i = count($info/preceding::info) ;
    delete $clone/alert/info[count(preceding::info) = $i] ;
    save :f concat('file', $i, '.xml') $clone ;
}
于 2015-10-22T12:19:03.610 回答
0

或者这可能比 Martin 的解决方案简单一些:

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

<xsl:template match="/">
 <xsl:for-each select="alert/info">
  <xsl:result-document href="language-{language}.xml">
    <alert>
      <xsl:copy-of select="../identifier"/>
      <xsl:copy-of select="."/>
    </alert>
  </xsl:result-document>
 </xsl:for-each>
</xsl:template>

</xsl:stylesheet>
于 2015-10-22T14:57:06.230 回答
0

使用像 Saxon 9 或 AltovaXML 或 XmlPrime 这样的 XSLT 2.0 处理器,您可以使用如下方法:

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

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

<xsl:template match="/">
  <xsl:apply-templates select="alert/info" mode="split"/>
</xsl:template>

<xsl:template match="info" mode="split">
  <xsl:result-document href="language-{language}.xml">
    <xsl:apply-templates select="/*">
      <xsl:with-param name="info" select="current()" tunnel="yes"/>
    </xsl:apply-templates>
  </xsl:result-document>
</xsl:template>

<xsl:template match="info">
  <xsl:param name="info" tunnel="yes"/>
  <xsl:if test=". is $info">
    <xsl:next-match/>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>

如果输入在某个命名空间中,则使用 eg <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xpath-default-namespace="urn:oasis:names:tc:emergency:cap:1.2">

如果要独立于命名空间运行 XSLT,请使用

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

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

<xsl:template match="/">
  <xsl:apply-templates select="*:alert/*:info" mode="split"/>
</xsl:template>

<xsl:template match="*:info" mode="split">
  <xsl:result-document href="language-{language}.xml">
    <xsl:apply-templates select="/*">
      <xsl:with-param name="info" select="current()" tunnel="yes"/>
    </xsl:apply-templates>
  </xsl:result-document>
</xsl:template>

<xsl:template match="*:info">
  <xsl:param name="info" tunnel="yes"/>
  <xsl:if test=". is $info">
    <xsl:next-match/>
  </xsl:if>
</xsl:template>

</xsl:stylesheet>
于 2015-10-22T12:07:31.930 回答