2013-06-24 5 views
1

J'ai données comme ça -XML manipulation clé/valeur à la condition en utilisant XSLT

<item> 
    <name>Bob</name> 
    <fav_food>pizza</fav_food> 
    <key>Salary</key> 
    <value /> 
    <value2>1000</value2> 
    <value3 /> 
</item> 

Je veux que ma sortie ressemble à ceci -

<item> 
    <name>Bob</name> 
    <fav_food>pizza</fav_food> 
    <Salary>1000</Salary> 
</item> 

Dans ce cas, Salaire obtient la valeur de 1000 car la valeur est vide et la valeur 2 ne l'est pas (la valeur a une priorité plus élevée que la valeur 2, qui a une priorité plus élevée que la valeur 3).

Il est garanti que la valeur, value2 et value3 existent tous, et qu'un seul d'entre eux n'est pas vide. Est-il possible d'utiliser une transformation XSLT pour le faire?

Actuellement, ceci est ma transformation.

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output indent="yes" omit-xml-declaration="yes" /> 
<xsl:strip-space elements="*" /> 

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

<xsl:template match="key"> 
    <xsl:element name="{substring-before(substring-after(.,'{'),'}')}"> 
     <xsl:choose> 
      <xsl:when test="value != ''"> 
       <xsl:value-of select="following-sibling::value" /> 
      </xsl:when> 
      <xsl:when test="value2 != ''"> 
       <xsl:value-of select="following-sibling::value2" /> 
      </xsl:when> 
      <xsl:when test="value3 != ''"> 
       <xsl:value-of select="following-sibling::value3" /> 
      </xsl:when> 
     </xsl:choose> 
    </xsl:element> 
</xsl:template> 
</xsl:stylesheet> 
+0

Pourrait-il y avoir plusieurs '' s par ''? Ce serait important de savoir. Je devine non, basé sur votre code. Aussi, votre code fonctionne-t-il correctement, et vous voulez juste une meilleure façon de le faire? Ou y a-t-il un problème avec votre code? Si oui, veuillez montrer la sortie réelle. – LarsH

+0

Je suis garanti seulement une clé par article. Mon code ne fonctionne pas, je reçois une chaîne vide pour toutes mes clés, quelles que soient mes valeurs. – Narabhut

+0

Chaînes vides où? S'il vous plaît montrer la sortie que vous obtenez. Aussi, pourquoi avez-vous 'substring-after()' etc. quand il n'y a pas de '{' dans votre entrée? Ou si l'entrée que vous avez montrée n'est pas réaliste de cette manière, montrez svp l'entrée réaliste. – LarsH

Répondre

3

Je pense que vous pouvez simplement faire

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output indent="yes" omit-xml-declaration="yes" /> 
<xsl:strip-space elements="*" /> 

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

<xsl:template match="key"> 
    <xsl:element name="{.}"> 
    <xsl:copy-of select="../(value, value2, value3)/text()"/> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="item/value | item/value2 | item/value3"/> 

</xsl:stylesheet> 

Vous voudrez peut-être ou besoin d'ajuster la génération de nom de l'élément, mais je n'ai pas appliqué votre name="{substring-before(substring-after(.,'{'),'}')}" comme je ne vois pas d'accolades dans votre échantillon d'entrée .

+1

J'allais suggérer 'xsl: valeur-de select =" ../ (valeur, valeur2, valeur3) "separator =" "' mais c'est la même idée. Mais étant donné le discours sur les "priorités", je soupçonne fortement que nous n'avons pas vu une spécification complète. –

+0

Cela fonctionne. Merci beaucoup Martin! – Narabhut