0
votes

Liste de nœuds Xpath 1.0 basée sur les noms de nœuds

Je n'aime pas demander de l'aide, mais cette fois je suis totalement coincé avec une requête xpath.

Veuillez jeter un œil à ce XML:

/doc/car/property[@id=name(/doc/attributes/*)]/attribute[@id=/doc/attributes/*/text()]

La voiture / les propriétés doivent être affichées en fonction des noms de nœuds des attributs. La sortie souhaitée est:

<property id="color"><attribute id="white" /></property>
<property id="size"><attribute id="small" /></property>

Le xpath

<doc>
  <car>
    <property id="color">
      <attribute id="black" />
      <attribute id="white" />
      <attribute id="green" />
    </property>
    <property id="size">
      <attribute id="small" />
      <attribute id="medium" />
      <attribute id="large" />
    </property>
  </car>
  <attributes>
    <color>white</color>
    <size>small</size>
  </attributes>
</doc>

ne produit que le premier nœud, car la fonction name () renvoie seulement le nom du premier élément.

Qui peut m'aider à trouver un xpath fonctionnel (XSLT 1.0)? Merci d'avance pour votre aide!


0 commentaires

4 Réponses :


0
votes

Vous pouvez y parvenir avec XSLT-1.0, mais pas seulement avec XPath-1.0, car dans XPath-1.0, vous ne pouvez renvoyer que le premier élément. Ce n'est pas un problème dans XSLT-1.0, car vous pouvez utiliser une boucle xsl: for-each , comme suit:

<property id="color"><attribute id="white"/></property>
<property id="size"><attribute id="small"/></property>

Ce code émet le XML suivant :

<xsl:for-each select="/doc/attributes/*">
    <property id="{/doc/car/property[@id=current()/local-name()]/@id}"><attribute id="{/doc/car/property[@id=current()/local-name()]/attribute[@id=current()/.]/@id}" /></property>
</xsl:for-each>

Comme on le voit, vos exigences semblent un peu redondantes, mais je suppose que votre plus grand scénario justifie les moyens.


5 commentaires

En fait, c'est un scénario plus grand. J'ai réduit le problème au strict minimum.


Et c'est bien. Mais la question pertinente est: ma solution vous aide-t-elle. et si non, pourquoi pas?


Une approche intéressante, merci beaucoup! Il faudra un jour ou deux avant que je puisse déterminer si toutes les expressions xpath du projet peuvent être remplacées ou non.


: Merci pour la matière à réflexion. C'est vrai, je dois quitter xpath et déterminer le résultat via XSL. Avec exsl: node-set (), je peux ensuite convertir le résultat RTF. La solution XSL semble très simple.


@ E.Wiest: Merci beaucoup pour vos trois échantillons. Mais ils sélectionnent n'importe quel attribut correspondant indépendamment de la propriété parent. Si le même ID d'attribut se produit dans plusieurs propriétés, il y a un conflit.



0
votes

Qu'en est-il de ces options (je ne vois toujours pas pourquoi vous utilisez name () car je ne vois aucun espace de noms dans vos exemples de données):

//property|//attribute[@id=//attributes/*]

//attribute[@id=//attributes/*]|//attribute[@id=//attributes/*]/parent::property

//property|//attribute[@id=substring-before(normalize-space(//attributes)," ") or @id=substring-after(normalize-space(//attributes)," ")]

La troisième option devrait fonctionner même si vous devez gérer un espace de noms pour le @id à l'intérieur du nœud attributes .

Résultat: p>

 Sortie


0 commentaires

0
votes

Ma solution de travail:

<xsl:stylesheet version="1.0">
  <xsl:template match="/">
    <xsl:for-each select="/doc/car/property">
      <property id="{@id}"> 
        <xsl:variable name="id" select="@id" />
        <xsl:copy-of select="attribute[@id=/doc/attributes/*[name()=$id]/text()]" />
      </property>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>


0 commentaires

0
votes

Autre solution sans utiliser de boucle:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
  <xsl:apply-templates select="doc/car/property"/>
</xsl:template>

<xsl:template match="property">
  <xsl:copy>
    <xsl:copy-of select="@*"/>
    <xsl:copy-of select="attribute[@id = /doc/attributes/*[name() = current()/@id]]"/>
  </xsl:copy>
</xsl:template>
</xsl:stylesheet>

Pour chaque propriété il copie le nœud d'élément et ses attributs. Ensuite, il copie ses enfants attribut ayant un id correspondant à l'élément respectif ci-dessous /doc/attributes.


0 commentaires