2009-03-30 10 views
0

J'ai besoin de traiter quotidiennement des documents XML de différents formats dans des enregistrements dans une base de données MySQL. Les données dont j'ai besoin de chaque document XML sont entrecoupées d'une bonne quantité de données dont je n'ai pas besoin, et les noms de nœuds de chaque document sont différents. Par exemple:Traitement de XML dans MySQL sous une bonne forme

Source # 1:

<object id="1"> 
    <title>URL 1</title> 
    <url>http://www.one.com</url> 
    <frequency interval="60" /> 
    <uselessdata>blah</uselessdata> 
</object> 
<object id="2"> 
    <title>URL 2</title> 
    <url>http://www.two.com</url> 
    <frequency interval="60" /> 
    <uselessdata>blah</uselessdata> 
</object> 

Source # 2:

<object"> 
    <objectid>1</objectid> 
    <thetitle>URL 1</thetitle> 
    <link>http://www.one.com</link> 
    <frequency interval="60" /> 
    <moreuselessdata>blah</moreuselessdata> 
</object> 
<object"> 
    <objectid>2</objectid> 
    <thetitle>URL 2</thetitle> 
    <link>http://www.two.com</link> 
    <frequency interval="60" /> 
    <moreuselessdata>blah</moreuselessdata> 
</object> 

... où j'ai besoin ID de l'objet, l'intervalle et l'URL.

Mes idées pour les approches sont:

1.) Avoir une fonction distincte pour analyser chaque document XML et créer itérativement la requête SQL à partir de cette fonction

2.) Avoir une fonction distincte parse chaque document et itérativement ajouter chaque objet à ma propre classe d'objet, et faire le travail SQL par une méthode de classe

3.) En utilisant XSLT pour convertir tous les documents dans un format XML commun, puis en écrivant un analyseur pour ce document.

Les documents XML eux-mêmes ne sont pas très volumineux, car la plupart seront inférieurs à 1 Mo. Je ne prévois pas que leur structure changera souvent (si jamais), mais il y a une forte possibilité que j'aurai besoin d'ajouter et d'enlever d'autres sources au fil du temps. Je suis ouvert à toutes les idées. En outre, désolé si les exemples XML ci-dessus sont tronqués ... ils ne sont pas très importants, juste une idée approximative pour montrer que les noms de nœuds dans chaque document sont différents.

Répondre

2

L'utilisation de XSLT est une surcharge. J'aime l'approche (2), ça a beaucoup de sens.

Utilisation de Python J'essayerais de créer une classe pour chaque type de document. La classe hériterait de dict et sur son __init__ analyserait le document donné et se remplirait avec 'id', 'interval' et 'url'.

Ensuite, le code dans main serait vraiment trivial, il suffit d'instancier les instances de ces classes (qui sont aussi des dicts) avec les documents appropriés, puis de les transmettre comme des dicts normaux.

+0

+1: Dans votre cas, les différents documents XML sont vraiment juste différents noms de tag. Ceux-ci, à leur tour, modifient simplement la chaîne XPath que vous utiliseriez dans les fonctions findTree et findall d'ElementTree. Les différentes options d'analyse XML sont vraiment faciles à faire. –

0

J'ai utilisé avec succès la variante de la troisième approche. Mais les documents que j'ai traités étaient beaucoup plus gros. Si c'est trop ou pas, ça dépend vraiment de votre aisance avec XSLT.

0

Si vos différents formats d'entrée sont sans ambiguïté, vous pouvez le faire:

<xsl:template match="object"> 
    <object> 
    <id><xsl:value-of select="@id | objectid" /></id> 
    <title><xsl:value-of select="title | thetitle" /></title> 
    <url><xsl:value-of select="url | link" /></url> 
    <interval><xsl:value-of select="frequency/@interval" /></interval> 
    </object> 
</xsl:template> 

Pour votre entrée exemple, ce produit:

<object> 
    <id>1</id> 
    <title>URL 1</title> 
    <url>http://www.one.com</url> 
    <interval>60</interval> 
</object> 
<object> 
    <id>2</id> 
    <title>URL 2</title> 
    <url>http://www.two.com</url> 
    <interval>60</interval> 
</object> 
<object> 
    <id>1</id> 
    <title>URL 1</title> 
    <url>http://www.one.com</url> 
    <interval>60</interval> 
</object> 
<object> 
    <id>2</id> 
    <title>URL 2</title> 
    <url>http://www.two.com</url> 
    <interval>60</interval> 
</object> 

Cependant, il peut y avoir des méthodes plus rapides pour parvenir à un utile résultat que d'utiliser XSLT. Il suffit de mesurer à quelle vitesse chaque approche est, et comment "laide" si elle se sent pour vous. J'aurais tendance à dire que XSLT est la solution la plus élégante/maintenable pour traiter XML. YMMV.

Si vos formats d'entrée sont ambigus et la solution ci-dessus produit des résultats erronés, une aproche plus explicite est nécessaire, le long des lignes de:

<xsl:template match="object"> 
    <object> 
    <xsl:choose> 
     <xsl:when test="@id and title and url and frequency/@interval"> 
     <xsl:apply-templates select="." mode="format1" /> 
     </xsl:when> 
     <xsl:when test="objectid and thetitle and link and frequency/@interval"> 
     <xsl:apply-templates select="." mode="format2" /> 
     </xsl:when> 
    </xsl:choose> 
    </object> 
</xsl:template> 

<xsl:template match="object" mode="format1"> 
    <id><xsl:value-of select="@id" /></id> 
    <title><xsl:value-of select="title" /></title> 
    <url><xsl:value-of select="url" /></url> 
    <interval><xsl:value-of select="frequency/@interval" /></interval> 
</xsl:template> 

<xsl:template match="object" mode="format2"> 
    <id><xsl:value-of select="objectid" /></id> 
    <title><xsl:value-of select="thetitle" /></title> 
    <url><xsl:value-of select="link" /></url> 
    <interval><xsl:value-of select="frequency/@interval" /></interval> 
</xsl:template> 
Questions connexes