Разделить XML-файл на несколько файлов на основе порогового значения - PullRequest
5 голосов
/ 14 декабря 2010

Мне нужно разделить следующий XML-файл на основе заранее определенного значения, для этого примера, давайте предположим, что я хочу ограничить узел "Item" тремя (3) в каждом созданном файле.

Вот пример входного 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>

Ответы [ 3 ]

6 голосов
/ 14 декабря 2010

Эта таблица стилей:

<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 голосов
/ 14 декабря 2010

Это преобразование :

<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 ", , где x и y - начальный и конечный индексы Item элементов, записанных в файле.

  4. EveryItem, который не запускает новый файл, удаляется пустым соответствующим шаблоном.Такие элементы обрабатываются в режиме «копирования».

0 голосов
/ 14 декабря 2010

Вы можете реализовать счетчик, который объявлен вне вашего цикла.Когда счетчик достигнет 3, сбросьте его и установите новое имя файла.В противном случае увеличивайте и добавляйте существующее имя файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...