2017-05-26 1 views
1

J'ai été chargé de mettre de l'ordre dans du code XML, donc malgré une DTD assez lâche, tout est déclaré de la même manière. Par exemple, dans les éléments ci-dessousComment déplacer un élément dans XSLT s'il existe

<all> 
<e> 
    <hg> 
     <hw>things</hw> 
     <posg><pos value="abc" /></posg> 
    </hg> 
    <sg><se1 /></sg> 
</e> 
<e> 
    <hg> 
     <hw>stuff</hw> 
     <posg><pos value="def" /></posg> 
    </hg> 
    <sg> 
     <se1> 
      <posg><pos value="ghi" /></posg> 
     </se1> 
    </sg> 
</e> 
</all> 

l'élément <posg> doit être un enfant de <se1> et non <hg>. En outre, si un élément <posg> existe déjà dans l'élément <se1>, je devrais alors créer un nouvel élément <se1> en tant que premier enfant de <sg>, puis déplacer l'élément <posg> de <hg> vers le nouvel élément <se1>.

En effet, alors, les deux éléments ci-dessus devraient ressembler à ceci après transformation

<all> 
    <e> 
     <hg> 
      <hw>things</hw> 
     </hg> 
     <sg> 
      <se1> 
       <posg><pos value="abc" /></posg> 
      </se1> 
     </sg> 
    </e> 
    <e> 
     <hg> 
      <hw>stuff</hw> 
     </hg> 
     <sg> 
      <se1> 
       <posg><pos value="def" /></posg> 
      </se1> 
      <se1> 
       <posg><pos value="ghi" /></posg> 
      </se1> 

     </sg> 
    </e> 
</all> 

Je me bats avec la façon de vérifier si l'élément <posg> rogue existe dans <hg> et prendre les mesures appropriées décrites ci-dessus.

Répondre

2

Utilisez le script suivant:

<?xml version="1.0" encoding="UTF-8" ?> 
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" /> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="sg"> 
    <xsl:copy> 
     <xsl:if test="../hg/posg"> 
     <se1><xsl:copy-of select="../hg/posg"/></se1> 
     </xsl:if> 
     <xsl:if test="se1/posg"> 
     <xsl:apply-templates select="@*|node()"/> 
     </xsl:if> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="hg/posg"/> 

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

Cette solution fonctionne, sauf qu'il ajoutera dans un enfant SE1 supplémentaire pour sg même s'il n'y a pas posg de copier en face de l'élément hg. Comment arrêtez-vous cela ou supprimez l'élément se1 vide généré? – Hmobius

+1

Pas de problème. J'ai enveloppé '' avec '' et '' (regardez dans le script). Ainsi, la balise '' n'est générée que s'il y a quelque chose à mettre dedans. –