根据阈值将XML文件拆分为多个文件

根据阈值将XML文件拆分为多个文件

问题描述:

我需要根据预定值拆分以下XML文件,对于此示例,假设我想将“Item”节点限制为每个内部的三个(3)文件已创建。根据阈值将XML文件拆分为多个文件

这里的一个样本输入XML文件:

<Items> 
    <Item> 
    <Title>Title 1</Title> 
    <DueDate>01-02-2008</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 2</Title> 
    <DueDate>01-02-2009</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 3</Title> 
    <DueDate>01-02-2010</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 4</Title> 
    <DueDate>01-02-2011</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 5</Title> 
    <DueDate>01-02-2012</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 6</Title> 
    <DueDate>01-02-2013</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 7</Title> 
    <DueDate>01-02-2013</DueDate> 
    </Item> 
</Items> 

基于的3阈值的所希望的输出,将三个文件,其中两个包含3“项”,并含有剩余的最后一个“项目”,这将是一个。

下面是我的XSLT样本,它允许我为每个项目分割它们,这会导致七个单独的文件,但是,我希望基于“Item”的某个限制来限制文件的大小节点每个文件。

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

<xsl:output method="xml" indent="yes" name="xml" /> 

<xsl:template match="/"> 

<xsl:for-each select="//Item"> 
    <xsl:variable name="nTitle" select="Title"/> 
    <xsl:variable name="filename" select="concat('Items\',$nTitle,'-','.xml')" /> 
    <xsl:value-of select="$filename" /> 
    <xsl:result-document href="{$filename}" format="xml"> 
     <xsl:copy-of select="."/> 
    </xsl:result-document> 
</xsl:for-each> 

</xsl:template> 
</xsl:stylesheet> 
+0

好问题,+1。查看我的答案获得简单的解决方案。 – 2010-12-13 22:00:41

这个样式表:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:param name="pItemsNumber" select="3"/> 
    <xsl:template match="Items"> 
     <xsl:for-each-group select="Item" 
          group-adjacent="(position()-1) idiv $pItemsNumber"> 
      <xsl:result-document href="Items\{current-grouping-key()}.xml"> 
       <Items> 
        <xsl:copy-of select="current-group()"/> 
       </Items> 
      </xsl:result-document> 
     </xsl:for-each-group> 
    </xsl:template> 
</xsl:stylesheet> 

输出:

<?xml version="1.0" encoding="UTF-8"?> 
<Items> 
    <Item> 
     <Title>Title 1</Title> 
     <DueDate>01-02-2008</DueDate> 
    </Item> 
    <Item> 
     <Title>Title 2</Title> 
     <DueDate>01-02-2009</DueDate> 
    </Item> 
    <Item> 
     <Title>Title 3</Title> 
     <DueDate>01-02-2010</DueDate> 
    </Item> 
</Items> 

<?xml version="1.0" encoding="UTF-8"?> 
<Items> 
    <Item> 
     <Title>Title 4</Title> 
     <DueDate>01-02-2011</DueDate> 
    </Item> 
    <Item> 
     <Title>Title 5</Title> 
     <DueDate>01-02-2012</DueDate> 
    </Item> 
    <Item> 
     <Title>Title 6</Title> 
     <DueDate>01-02-2013</DueDate> 
    </Item> 
</Items> 

<?xml version="1.0" encoding="UTF-8"?> 
<Items> 
    <Item> 
     <Title>Title 7</Title> 
     <DueDate>01-02-2013</DueDate> 
    </Item> 
</Items> 

编辑:糟糕!

+0

感谢亚历杭德罗,做了这份工作。 – Brian 2010-12-14 03:43:43

+0

@Brian:不客气。 – 2010-12-14 12:34:34

您可以实现一个在循环之外声明的计数器。当计数器命中3时,重置它并设置一个新的文件名。否则,增加并追加到现有的文件名。

这种转变

<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:strip-space elements="*"/> 
<xsl:param name="pSplitNum" select="3"/> 

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

<xsl:template match="Item[position() mod $pSplitNum eq 1]"> 
    <xsl:result-document href= 
    "file{position()}-{min((position()+$pSplitNum -1, count(/*/Item)))}.xml"> 
    <Items> 
     <xsl:call-template name="identity"/> 
     <xsl:apply-templates mode="copy" select= 
     "following-sibling::Item[position() lt $pSplitNum]"/> 
    </Items> 
    </xsl:result-document> 
</xsl:template> 
<xsl:template match="/*"><xsl:apply-templates/></xsl:template> 
<xsl:template match="Item[position() mod $pSplitNum ne 1]"/> 
</xsl:stylesheet> 

时所提供的XML文档应用:

<Items> 
    <Item> 
    <Title>Title 1</Title> 
    <DueDate>01-02-2008</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 2</Title> 
    <DueDate>01-02-2009</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 3</Title> 
    <DueDate>01-02-2010</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 4</Title> 
    <DueDate>01-02-2011</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 5</Title> 
    <DueDate>01-02-2012</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 6</Title> 
    <DueDate>01-02-2013</DueDate> 
    </Item> 
    <Item> 
    <Title>Title 7</Title> 
    <DueDate>01-02-2013</DueDate> 
    </Item> 
</Items> 

产生想要三个XML文件

Saxon 9.1.0.5J from Saxonica 
Java version 1.6.0_22 
Stylesheet compilation time: 645 milliseconds 
Processing file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml 
Building tree for file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml using class net.sf.saxon.tinytree.TinyBuilder 
Tree built in 10 milliseconds 
Tree size: 38 nodes, 119 characters, 0 attributes 
Loading net.sf.saxon.event.MessageEmitter 
Writing to file:/C:/Program%20Files/Java/jre6/bin/file1-3.xml 
Writing to file:/C:/Program%20Files/Java/jre6/bin/file4-6.xml 
Writing to file:/C:/Program%20Files/Java/jre6/bin/file7-7.xml 
Execution time: 101 milliseconds 
Memory used: 11453088 
NamePool contents: 20 entries in 20 chains. 6 prefixes, 7 URIs 

请注意

  1. 这是身份的规则模式的简单应用。

  2. Item开始一个新的文件匹配,它会导致在顶部元件的包装,其本身下一$ pSplitNum -1处理(或任何保留在最后一组),并输出其作为单个结果文件(文件)。

  3. 创建的每个文件的名称是:“FILEX-y.xml”,其中xy的出发和书面文件中的Item元素的结束索引。

  4. 每个Item即不开始新文件被删除由一个空的匹配模板。这些元素在“复制”模式下处理。