2010-12-13 59 views
5

Necesito dividir el siguiente archivo XML basado en un valor predeterminado, para este ejemplo, supongamos que quiero limitar el nodo "Artículo" a tres (3) dentro de cada archivo creado.Dividir archivo XML en varios archivos según un valor de umbral

Aquí hay un ejemplo de archivo XML de entrada:

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

La salida deseada en función del valor umbral del 3, habría tres archivos, dos de los cuales contienen 3 "artículo", y el último contiene el restante "artículos", que sería uno.

Aquí hay una muestra de mi XSLT que me permite dividirlos para cada elemento, lo que resulta en siete archivos separados, sin embargo, lo que deseo es limitar el tamaño del archivo basado en un cierto límite de "Artículo" nodo por archivo.

<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

Buena pregunta, +1. Vea mi respuesta para una solución simple. –

Respuesta

6

Esta hoja de estilo:

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

Salida:

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

Editar: Ups!

+0

Gracias Alejandro, que hizo el trabajo. – Brian

+0

@Brian: De nada. –

-1

Puede implementar un contador que esté declarado fuera de su bucle. Cuando el contador llegue a 3, reinícielo y establezca un nuevo nombre de archivo. De lo contrario, incremente y anexe al nombre de archivo existente.

0

Esta transformación:

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

cuando se aplica en el documento XML proporcionado:

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

produce los buscados tres archivos 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 

hacer la nota:

  1. Esta es una sencilla aplicación de la regla patrón identidad.

  2. Cada Item iniciar un nuevo archivo se corresponde y hace que la envoltura en un elemento superior, el procesamiento de la misma y la siguiente pSplitNum $ -1 (o lo que queda en el último grupo), y dar salida a esto como una solo resultado-documento (archivo).

  3. El nombre de cada archivo creado es: "la sílice-y.xml", dondex y y son el inicio y final de los índices Item elementos escritos en el archivo.

  4. Cada Item que no está comenzando un nuevo archivo se elimina por una plantilla vacía correspondiente. Dichos elementos se procesan en modo "copia".

Cuestiones relacionadas