将XML文件拆分为多个

时间:2017-01-05 19:53:07

标签: xml xslt xslt-2.0

之前可能会问过这个问题,但我有一个XML文件需要拆分成单独的文件。

文件是:

<?xml version="1.0" encoding="UTF-8"?>
<invoices>
    <invoice>
        <data>

        </data>
    </invoice>
    <invoice>
        <data>

        </data>
    </invoice>
</invoices>

我有我的代码将其拆分为:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" exclude-result-prefixes="xsl">
    <xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="no" indent="yes"/>
    <xsl:template match="/">
        <tosplit>
            <xsl:for-each-group select="//invoice" group-by="ceiling(position() div 1)">
                <xsl:apply-templates select="/" mode="copy">
                    <xsl:with-param name="currentgroup" select="current-group()"/>
                </xsl:apply-templates>
            </xsl:for-each-group>
        </tosplit>
    </xsl:template>
    <xsl:template match="@*|node()" mode="copy">
        <xsl:param name="currentgroup"/>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="copy">
                <xsl:with-param name="currentgroup" select="current-group()"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="invoices" mode="copy">
        <xsl:param name="currentgroup"/>
        <xsl:copy>
            <xsl:apply-templates select="@*" mode="copy"/>
            <xsl:apply-templates select="$currentgroup" mode="copy"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

然而,这并不能解决问题。我希望每个文件看起来像

<?xml version="1.0" encoding="UTF-8"?>
<tosplit>
   <invoices>
      <invoice>
         <data>

         </data>
      </invoice>
   </invoices>
</tosplit>

任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

如果您可以访问oXygen中的Saxon 9 PE或EE等XSLT 3.0处理器或XMLSpy 2017中的Altova's Raptor,那么您只需要

public static bool HasClass(this HtmlNode node, params string[] classValueArray)
    {
        var classValue = node.GetAttributeValue("class", "");
        var classValues = classValue.Split(' ');
        return classValueArray.All(c => classValues.Contains(c));
    }

为每个<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:math="http://www.w3.org/2005/xpath-functions/math" exclude-result-prefixes="xs math" version="3.0"> <xsl:mode on-no-match="shallow-skip" streamable="yes"/> <xsl:strip-space elements="*"/> <xsl:output indent="yes"/> <xsl:template match="invoice"> <xsl:result-document href="invoice-split{position()}.xml"> <xsl:copy-of select="snapshot(.)/root()"/> </xsl:result-document> </xsl:template> </xsl:stylesheet> 元素创建一个结果文档。

答案 1 :(得分:0)

让我们先看看你的代码无效的原因

<xsl:template match="/">
        <tosplit>
            <xsl:for-each-group select="//invoice" group-by="ceiling(position() div 1)">
                <xsl:apply-templates select="/" mode="copy">
                    <xsl:with-param name="currentgroup" select="current-group()"/>
                </xsl:apply-templates>
            </xsl:for-each-group>
        </tosplit>
    </xsl:template>

我真的不知道你对那个分组属性的想法。如果X是一个整数(因为position()是),那么ceiling(X div 1)将返回X不变。所以它与group-by =“position()”相同,并且由于每个项目的位置不同,每个项目将进入一个单独的组。这意味着您的代码是一种令人费解的方式:

<xsl:template match="/">
    <tosplit>
        <xsl:for-each select="//invoice" >
             <xsl:apply-templates select="/" mode="copy">
                 <xsl:with-param name="currentgroup" select="."/>
             </xsl:apply-templates>
        </xsl:for-each>
   </tosplit>
</xsl:template>

反过来又无法实现任何无法自然完成的事情

<xsl:template match="/">
    <tosplit>
        <xsl:apply-templates select="//invoice" mode="copy"/>
   </tosplit>
</xsl:template>

基本上,你没有进行任何分组,从你的问题陈述中你不需要进行任何分组,因此很难看出这段代码是什么。

同时,您说您希望为每个发票生成一个文件,但您的代码不会尝试生成多个输出文件。