2010-12-13 107 views
5

我需要根據預定值拆分以下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

回答

6

這個樣式表:

<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

-1

您可以實現一個在循環之外聲明的計數器。當計數器命中3時,重置它並設置一個新的文件名。否則,增加並追加到現有的文件名。

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: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即不開始新文件被刪除由一個空的匹配模板。這些元素在「複製」模式下處理。

相關問題