À l'aide de xslt, transformez un document XML en fonction du contenu d'un deuxième document XML.

StackOverflow https://stackoverflow.com/questions/647324

  •  22-07-2019
  •  | 
  •  

Question

J'ai un ensemble de documents qui définit implicitement les champs autorisés pour un deuxième ensemble d'objets à transformer en un troisième ensemble de documents ( qui " règles " document à utiliser dépend du contenu du fichier en cours de transformation), par exemple.

<!-- One example rules document --> 
<document object="obj1_rules">
<field name="A"/>
<field name="B"/>
<field name="C"/>
</document>

<!-- Document to be tranformed based upon obj1_rules--> 
<document object="obj1">
<field name="A"/>
<field name="B"/>
<field name="C"/>
<field name="D"/>
<field name="E"/>
</document>

<!-- Desired result--> 
<document object="obj1">
<newfield name="A"/>
<newfield name="B"/>
<newfield name="C"/>
</document>

Est-il possible d'effectuer cette transformation à l'aide de xslt?

Je vois que " Il n'y a aucun moyen dans XSLT de construire des expressions XPath (par exemple, des références variables) au moment de l'exécution. & ; Donc, je n'ai pas de chance, ou je regarde ce problème de manière incorrecte? Merci!

Était-ce utile?

La solution

Voici une solution simple :

Cette transformation :

<xsl:stylesheet version="1.0" 
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
<!--                                                   -->  
    <xsl:variable name="vrtfRules">
        <document object="obj1_rules">
            <field name="A"/>
            <field name="B"/>
            <field name="C"/>
        </document>
    </xsl:variable>
<!--                                                   -->  
    <xsl:variable name="vRules" select=
     "document('')/*/xsl:variable
                   [@name = 'vrtfRules']
                     /*
     "/>
<!--                                                   -->  
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>
<!--                                                   -->  
    <xsl:template match="field">
      <xsl:if test="@name = $vRules/*/@name">
        <newfield>
          <xsl:apply-templates select="node()|@*"/>
        </newfield>
      </xsl:if>
    </xsl:template>
</xsl:stylesheet>

lorsqu'il est appliqué au document XML source fourni à l'origine:

<document object="obj1">
    <field name="A"/>
    <field name="B"/>
    <field name="C"/>
    <field name="D"/>
    <field name="E"/>
</document>

produit le résultat souhaité:

<document object="obj1">
   <newfield name="A"/>
   <newfield name="B"/>
   <newfield name="C"/>
</document>

Notez que le " document de règles " est dans la feuille de style juste pour la compacité. Lorsqu'il s'agit d'un document séparé, seul le document () utilisée doit être ajustée avec le href réel.

Autres conseils

Je simplifie peut-être excessivement, mais existe-t-il une raison pour laquelle votre "document de règles" " ne peut pas simplement être un XSLT?

Eh bien, je vois pourquoi vous aimeriez avoir des règles dans un simple fichier xml plutôt que dans une feuille de style xsl à part entière, mais vous sautez simplement une étape.

Vous devez créer une feuille de style xsl qui transformera votre document de règles xml en une feuille de style xsl que vous appliquerez ensuite sur votre code source xml.

Le truc est d'utiliser des espaces de noms et de ne pas être dérouté par la combinaison de règles xsl appliquées et de règles xsl générées.

    <?xml version="1.0" ?>
    <xsl:stylesheet
        xmlns="YOUR_NAMESPACE_HERE"
        xmlns:output="http://www.w3.org/1999/XSL/Transform"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0">

        <xsl:output
            method="xml"
            indent="yes"
            media-type="text/xsl" />

        <xsl:template match="/">
            <output:stylesheet version="2.0">
                <xsl:apply-templates />
            </output:stylesheet>
        </xsl:template>

        <xsl:template match="document[@object]">
            <output:template match="document[@object='{@object}']">
                <output:copy>
                    <xsl:apply-templates />
                </output:copy>
            </output:template>
        </xsl:template>

        <xsl:template match="field[@name]">
            <output:if test="field[@name='{@name}']">
                <output:copy-of select="field[@name='{@name}']" />
            </output:if>
        </xsl:template>

    </xsl:stylesheet>

J'ai supposé que vous utiliseriez le même attribut d'objet document dans les règles et dans les documents eux-mêmes (c'est beaucoup plus simple imo).

Ainsi, vous exécutez votre document de règles à travers la feuille de style ci-dessus. Le résultat est une nouvelle feuille de style xsl qui fait exactement ce que vous décrivez dans votre document de règles xml. Vous appliquez ensuite cette feuille de style résultante sur votre document source et vous devriez obtenir le résultat que vous attendez.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top