11 votes

Comment diviser un gros fichier xml ?

Nous exportons des "enregistrements" vers un fichier xml ; l'un de nos clients s'est plaint que le fichier était trop volumineux pour être traité par son autre système. Je dois donc diviser le fichier, tout en répétant la "section d'en-tête" dans chacun des nouveaux fichiers.

Je cherche donc quelque chose qui me permette de définir des xpaths pour la ou les sections qui doivent toujours être produites, et un autre xpath pour les "lignes" avec un paramètre qui indique le nombre de lignes à mettre dans chaque fichier et comment nommer les fichiers.

Avant de commencer à écrire un code .net personnalisé pour faire cela ; Existe-t-il un outil de ligne de commande standard qui fonctionne sous Windows et qui permet de le faire ? ?

(Comme je sais programmer en C#, je suis plus enclin à écrire du code qu'à essayer de m'embrouiller avec du xsl complexe, etc, mais une solution "de soi" serait préférable à du code personnalisé).

4voto

ewroman Points 605

Téléchargez d'abord foxe xml editor à partir de ce lien http://www.firstobject.com/foxe242.zip

Regarder cette vidéo http://www.firstobject.com/xml-splitter-script-video.htm La vidéo explique le fonctionnement du code fractionné.

Il y a un code script sur cette page (qui commence par split() ) copier le code et dans le programme de l'éditeur xml faire un "Nouveau programme" sous le "Fichier". Collez le code et sauvegardez-le. Le code est le suivant :

split()
{
  CMarkup xmlInput, xmlOutput;
  xmlInput.Open( "**50MB.xml**", MDF_READFILE );
  int nObjectCount = 0, nFileCount = 0;
  while ( xmlInput.FindElem("//**ACT**") )
  {
    if ( nObjectCount == 0 )
    {
      ++nFileCount;
      xmlOutput.Open( "**piece**" + nFileCount + ".xml", MDF_WRITEFILE );
      xmlOutput.AddElem( "**root**" );
      xmlOutput.IntoElem();
    }
    xmlOutput.AddSubDoc( xmlInput.GetSubDoc() );
    ++nObjectCount;
    if ( nObjectCount == **5** )
    {
      xmlOutput.Close();
      nObjectCount = 0;
    }
  }
  if ( nObjectCount )
    xmlOutput.Close();
  xmlInput.Close();
  return nFileCount;
}

Modifiez les champs marqués en gras (ou ** **) en fonction de vos besoins. (ceci est également exprimé sur la page vidéo)

Dans la fenêtre de l'éditeur xml, faites un clic droit et cliquez sur RUN (ou simplement sur F9). La barre de sortie de la fenêtre indique le nombre de fichiers générés.

Remarque : Le nom du fichier d'entrée peut être "C:\\Users\\AUser\\Desktop\\a_xml_file.xml" (double barre oblique) et le fichier de sortie "C:\\Users\\AUser\\Desktop\\anoutputfolder\\piece" + nFileCount + ".xml"

3voto

Robert Rossney Points 43767

Il n'existe pas de solution générale à ce problème, car il y a tellement de façons différentes dont votre source XML peut être structurée.

Il est relativement simple de construire une transformation XSLT qui produira une tranche d'un document XML. Par exemple, étant donné ce XML :

<header>
  <data rec="1"/>
  <data rec="2"/>
  <data rec="3"/>
  <data rec="4"/>
  <data rec="5"/>
  <data rec="6"/>
</header>

vous pouvez produire une copie du fichier ne contenant que des data à l'intérieur d'un certain intervalle avec cette XSLT :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>
  <xsl:param name="startPosition"/>
  <xsl:param name="endPosition"/>

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

  <xsl:template match="header">
    <xsl:copy>
      <xsl:apply-templates select="data"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="data">
    <xsl:if test="position() &gt;= $startPosition and position() &lt;= $endPosition">
      <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
    </xsl:if>
  </xsl:template>

</xsl:stylesheet>

(Notez, en passant, que cette méthode est basée sur la transformation d'identité et qu'elle fonctionne même si header n'est pas l'élément de premier niveau).

Vous devez encore compter les data dans le XML source, et exécuter la transformation de façon répétée avec les valeurs de $startPosition y $endPosition qui sont appropriés à la situation.

3voto

loomi Points 416

Comme nous l'avons déjà mentionné, la xml_split de l'application Perl paquet XML::Twig fait un excellent travail.

Utilisation

xml_split < bigFile.xml

#or if compressed e.g.
bzcat bigFile.xml.bz2 | xml_split

Sans aucun argument xml_split crée un fichier par nœud enfant de premier niveau.

Il y a paramètres pour spécifier le nombre d'éléments que vous voulez par fichier ( -g ) ou la taille approximative ( -s <Kb|Mb|Gb> ).

Installation

Fenêtres

Regardez ici

Linux

sudo apt-get install xml-twig-tools

2voto

Gfy Points 2129

Xml_split - divise d'énormes documents XML en morceaux plus petits

http://www.perlmonks.org/index.pl?node_id=429707

http://metacpan.org/pod/XML::Twig

1voto

Oded Points 271275

Il n'y a rien d'intégré qui puisse gérer facilement cette situation.

Votre approche semble raisonnable, même si je commencerais probablement par un document "squelette" contenant les éléments qui doivent être répétés et que je générerais plusieurs documents avec les "enregistrements".


Mise à jour :

Après quelques recherches, j'ai trouvé este décrivant un moyen de découper des fichiers à l'aide de XSLT.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X