2010-03-11 12 views
1

Je reçois un énorme fichier XML contenant une liste d'émissions TV. Et je dois le diviser en petits fichiers contenant toutes les émissions pour une journée seulement. J'ai réussi à cela mais j'ai deux problèmes avec l'en-tête xml et un nœud qui y est plusieurs fois.Un moyen de diviser un énorme fichier XML en fichiers xml plus petits avec XSL

La structure du XML est le suivant:

<?xml version="1.0" encoding="UTF-8"?> 
<broadcasts> 
    <broadcast> 
    <id>4637445812</id> 
    <week>39</week> 
    <date>2009-09-22</date> 
    <time>21:45:00:00</time> 
     ... (some more) 
    </broadcast> 
    ... (long list of broadcast nodes) 
</broadcasts> 

Mon XSL ressemble à ceci:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     xmlns:redirect="http://xml.apache.org/xalan/redirect" 
     extension-element-prefixes="redirect" 
     version="1.0"> 
    <!-- mark the CDATA escaped tags --> 
    <xsl:output method="xml" cdata-section-elements="title text" 
     indent="yes" omit-xml-declaration="no" /> 

    <xsl:template match="broadcasts"> 
     <xsl:apply-templates /> 
    </xsl:template> 

    <xsl:template match="broadcast"> 
    <!-- Build filename PRG_YYYYMMDD.xml --> 
    <xsl:variable name="filename" select="concat(substring(date,1,4),substring(date,6,2))"/> 
    <xsl:variable name="filename" select="concat($filename,substring(date,9,2))" /> 
    <xsl:variable name="filename" select="concat($filename,'.xml')" /> 
    <redirect:write select="concat('PRG_',$filename)" append="true">  

     <schedule> 
     <broadcast program="TEST"> 
      <!-- format timestamp in specific way --> 
      <xsl:variable name="tmstmp" select="concat(substring(date,9,2),'/')"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,substring(date,6,2))"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,'/')"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,substring(date,1,4))"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,' ')"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,substring(time,1,5))"/> 

      <timestamp><xsl:value-of select="$tmstmp"/></timestamp> 
      <xsl:copy-of select="title"/> 
      <text><xsl:value-of select="subtitle"/></text> 

      <xsl:variable name="newVps" select="concat(substring(vps,1,2),substring(vps,4,2))"/> 
      <xsl:variable name="newVps" select="concat($newVps,substring(vps,7,2))"/> 
      <xsl:variable name="newVps" select="concat($newVps,substring(vps,10,2))"/> 
      <vps><xsl:value-of select="$newVps"/></vps>      
      <nextday>false</nextday>    
     </broadcast>  
     </schedule> 
    </redirect:write> 
    </xsl:template> 
</xsl:stylesheet> 

Mes XMLs de sortie sont comme ceci:

PRG_20090512.xml:

<?xml version="1.0" encoding="UTF-8"?> 
    <schedule> 
    <broadcast program="TEST"> 
     <timestamp>01/03/2010 06:00</timestamp> 
     <title><![CDATA[TELEKOLLEG Geschichte ]]></title> 
     <text><![CDATA[Giganten in Fernost]]></text> 
     <vps>06000000</vps> 
     <nextday>false</nextday> 
    </broadcast> 
    </schedule> 
<?xml version="1.0" encoding="UTF-8"?> <!-- don't want this --> 
    <schedule> <!-- don't want this --> 
    <broadcast program="TEST"> 
     <timestamp>01/03/2010 06:30</timestamp> 
     <title><![CDATA[Die chemische Bindung]]></title> 
     <text/> 
     <vps>06300000</vps> 
     <nextday>false</nextday> 
    </broadcast> 
    </schedule> 
<?xml version="1.0" encoding="UTF-8"?> 
...and so on 

Je peux mettre omit-xml-declaration = "yes" dans la déclaration de sortie, mais je n'ai pas d'en-tête xml. J'ai essayé de mettre un chèque si l'étiquette est déjà dans la sortie, mais a omis de sélectionner des noeuds dans la sortie ...

C'est ce que j'ai essayé:

<xsl:choose> 
    <xsl:when test="count(schedule) = 0"> <!-- schedule needed --> 
    <schedule> 
     <broadcast> 
    ... 
    <xsl:otherwise> <!-- no schedule needed --> 
    <broadcast> 
    ... 

Merci pour toute aide, comme Je ne sais pas comment gérer cela. ;. ( yeti

Répondre

1

un seul fichier à la fois, contenant toutes les diffusions pour cette date

Cela devient un problème de regroupement des éléments d'entrée par date. Comme Xalan est XSLT 1.0, vous le faites avec des clés.

Nous définissons une clé pour regrouper les diffusions par date. Le nous sélectionnons chaque diffusion qui est le premier de sa date. Sélectionnez ensuite toutes les diffusions pour la même date à l'aide de la fonction de touche.

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:redirect="http://xml.apache.org/xalan/redirect" 
       extension-element-prefixes="redirect" 
       version="1.0"> 

    <!-- mark the CDATA escaped tags --> 
    <xsl:output method="xml" cdata-section-elements="title text" indent="yes" omit-xml-declaration="no" /> 

    <xsl:key name="date" match="broadcast" use="date" /> 

    <xsl:template match="broadcasts"> 
     <xsl:apply-templates select="broadcast[generate-id(.)=generate-id(key('date',date)[1])]"/> 
    </xsl:template> 

    <xsl:template match="broadcast"> 
     <!-- Build filename PRG_YYYYMMDD.xml --> 
     <xsl:variable name="filename" select="concat(substring(date,1,4),substring(date,6,2))"/> 
     <xsl:variable name="filename" select="concat($filename,substring(date,9,2))" /> 
     <xsl:variable name="filename" select="concat($filename,'.xml')" /> 

     <redirect:write select="concat('PRG_',$filename)" append="true">   

      <schedule> 
       <xsl:apply-templates select="key('date',date)" mode="broadcast" /> 
      </schedule> 

     </redirect:write> 

    </xsl:template> 

    <xsl:template match="broadcast" mode="broadcast"> 
     <broadcast program="TEST"> 
      <!-- format timestamp in specific way --> 
      <xsl:variable name="tmstmp" select="concat(substring(date,9,2),'/')"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,substring(date,6,2))"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,'/')"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,substring(date,1,4))"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,' ')"/> 
      <xsl:variable name="tmstmp" select="concat($tmstmp,substring(time,1,5))"/> 

      <timestamp><xsl:value-of select="$tmstmp"/></timestamp> 
      <xsl:copy-of select="title"/> 
      <text><xsl:value-of select="subtitle"/></text> 

      <xsl:variable name="newVps" select="concat(substring(vps,1,2),substring(vps,4,2))"/> 
      <xsl:variable name="newVps" select="concat($newVps,substring(vps,7,2))"/> 
      <xsl:variable name="newVps" select="concat($newVps,substring(vps,10,2))"/> 
      <vps><xsl:value-of select="$newVps"/></vps>          
      <nextday>false</nextday>        
     </broadcast> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Merci beaucoup! C'est exactement ce dont j'avais besoin! ;) –

0

Enveloppez vos éléments de calendrier avec un parent unique et voir si cela fait disparaître le problème

Je ne suis pas au courant de ce problème, mais je pense qu'il est causé par votre essai pour générer des documents XML avec plusieurs éléments de niveau supérieur Chaque document XML doit avoir exactement un élément de niveau supérieur (une exigence stupide si vous me le demandez, par exemple, il rend le XML inadapté aux fichiers journaux, mais c'est comme ça)