2015-12-03 2 views
0

Je me demande comment il se fait par XSLT 1.0 une transformation qui passe le résultat d'un modèle comme une entrée pour un autre dans un seul fichier .xslt:XSLT 1.0 - Exécution d'un modèle sur le résultat d'un autre modèle

Raw XML d'entrée> call-template (1)> reformaté XML> call-template (2) sur la reformaté XML

Case:

Je veux écrire un modèle de re- arrangez un XML pour que les attributs deviennent des éléments; puis exécutez un autre modèle sur le fichier XML résultant de la première pour supprimer les doublons. Je peux avoir deux fichiers xsl et passer le résultat de la première transformation à la seconde. Cependant, je veux le faire en un xslt.

Le xml d'entrée brute est la suivante:

<?xml version="1.0" encoding="UTF-8"?> 
<resources> 
    <resource> 
     <properties> 
      <property name="name" value="Foo"/> 
      <property name="service" value="Bar"/> 
      <property name="version" value="1"/> 
     </properties> 
    </resource> 
    <resource> 
     <properties> 
      <property name="name" value="Foo"/> 
      <property name="service" value="Bar"/> 
      <property name="version" value="2"/> 
     </properties> 
    </resource> 
    <resource> 
     <properties> 
      <property name="name" value="AnotherFoo"/> 
      <property name="service" value="AnotherBar"/> 
      <property name="version" value="1"/> 
     </properties>a 
    </resource> 
</resources> 

Lorsque je demande la xslt suivante:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    exclude-result-prefixes="msxsl"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:template name="attributes-to-elements" match="/resources"> 
     <xsl:call-template name="get-resources" /> 
    </xsl:template> 

    <xsl:template name="get-resources"> 
     <xsl:text>&#xa;</xsl:text> 
     <products> 
      <xsl:for-each select="resource"> 
       <xsl:call-template name="convert-attributes-to-elements" /> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 

    <xsl:template name="convert-attributes-to-elements"> 
     <product> 
      <name> 
       <xsl:value-of select="properties/property[@name='name']/@value" /> 
      </name> 
      <service> 
       <xsl:value-of select="properties/property[@name='service']/@value" /> 
      </service> 
     </product> 
    </xsl:template> 
</xsl:stylesheet> 

Je suis capable de reformater le xml sans les versions et obtenir la sortie qui ne contient pas de versions et les attributs sont devenus des éléments:

<?xml version="1.0" encoding="UTF-8"?> 
<products> 
    <product> 
     <name>Foo</name> 
     <service>Bar</service> 
    </product> 
    <product> 
     <name>Foo</name> 
     <service>Bar</service> 
    </product> 
    <product> 
     <name>AnotherFoo</name> 
     <service>AnotherBar</service> 
    </product> 
</products> 

Maintenant, la chose que je veux est Pour transmettre ce fichier XML modifié à un modèle en tant que , entrez le code XML et supprimez les doublons. Enfin, je veux obtenir un xml comme:

<?xml version="1.0" encoding="UTF-8"?> 
<products> 
    <product> 
     <name>Foo</name> 
     <service>Bar</service> 
    </product> 
    <product> 
     <name>AnotherFoo</name> 
     <service>AnotherBar</service> 
    </product> 
</products> 
+0

Votre question sur la façon d'appliquer un modèle au résultat d'un autre modèle (et scénario donné est seulement un exemple), ou demandez-vous comment réaliser la tâche dans l'exemple? Si ce dernier, il peut être fait en un seul passage. –

Répondre

1

Je voudrais utiliser un mode pour séparer les étapes de traitement, et bien sûr dans XSLT 1.0, vous devez également une fonction d'extension comme exsl:node-set ou msxsl:node-set pour être en mesure de traiter plus d'un fragment d'arbre résultat créé dans un autre modèle:

<?xml version="1.0" encoding="utf-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:exsl="http://exslt.org/common" 
    exclude-result-prefixes="msxsl exsl"> 

    <xsl:output method="xml" indent="yes" /> 

    <xsl:key name="group" match="product" use="concat(name, '|', service)"/> 

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

    <xsl:template match="product[not(generate-id() = generate-id(key('group', concat(name, '|', service))[1]))]" mode="step2"/> 

    <xsl:template name="attributes-to-elements" match="/resources"> 
     <xsl:variable name="step1-rtf"> 
      <xsl:call-template name="get-resources" /> 
     </xsl:variable> 
     <xsl:apply-templates select="exsl:node-set($step1-rtf)/*" mode="step2"/> 
    </xsl:template> 

    <xsl:template name="get-resources"> 
     <xsl:text>&#xa;</xsl:text> 
     <products> 
      <xsl:for-each select="resource"> 
       <xsl:call-template name="convert-attributes-to-elements" /> 
      </xsl:for-each> 
     </products> 
    </xsl:template> 

    <xsl:template name="convert-attributes-to-elements"> 
     <product> 
      <name> 
       <xsl:value-of select="properties/property[@name='name']/@value" /> 
      </name> 
      <service> 
       <xsl:value-of select="properties/property[@name='service']/@value" /> 
      </service> 
     </product> 
    </xsl:template> 
</xsl:stylesheet> 

Vous devez vérifier si votre processeur XSLT prend en charge exsl:node-set, MSXML a besoin msxsl:node-set à la place.

+0

En effet, cette chose MSXML est là parce que j'ai créé le fichier XSLT dans Visual Studio et laissé l'en-tête tel qu'il est. Je vais faire ce transfert via la classe javax.xml.transform.Transformer dans Java 1.6 – vahdet

+0

Essayez le 'exsl: node-set', peut-être que cela fonctionne. Sinon, essayez 'xmlns: xalan =" http://xml.apache.org/xalan "' et 'xalan: node-set' à la place. Mais le Transformer peut être n'importe quelle implémentation. –

2

Cela peut être fait en une seule passe, si vous voulez:

XSLT 1,0

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

<xsl:key name="k" 
     match="resource" 
     use="concat(properties/property[@name='name']/@value, '|', properties/property[@name='service']/@value)" 
/> 

<xsl:template match="/resources"> 
    <products> 
     <xsl:apply-templates select="resource[count(. | key('k', concat(properties/property[@name='name']/@value, '|',  properties/property[@name='service']/@value))[1]) = 1]"/> 
    </products> 
</xsl:template> 

<xsl:template match="resource"> 
    <product> 
     <xsl:copy-of select="@id"/> 
     <name> 
      <xsl:value-of select="properties/property[@name='name']/@value" /> 
     </name> 
     <service> 
      <xsl:value-of select="properties/property[@name='service']/@value" /> 
     </service> 
    </product> 
</xsl:template> 

</xsl:stylesheet>