Question

Il doit exister un moyen générique de transformer certains fichiers XML hiérarchiques tels que:

<element1 A="AValue" B="BValue">
   <element2 C="DValue" D="CValue">
      <element3 E="EValue1" F="FValue1"/>
      <element3 E="EValue2" F="FValue2"/>
   </element2>
   ...
</element1>

dans le XML aplati (html) en sélectionnant les attributs sélectionnés et en fournissant différentes étiquettes pour les attributs qui deviennent des en-têtes de colonnes.

<table>
   <tr>
     <th>A_Label</th>
     <th>D_Label</th>
     <th>E_Label</th>
     <th>F_Label</th>
   </tr>
   <tr>
     <td>AValue</td>
     <td>DValue</td>
     <td>EValue1</td>
     <td>FValue1</td>
   </tr>
   <tr>
     <td>AValue</td>
     <td>DValue</td>
     <td>EValue2</td>
     <td>FValue2</td>
   </tr>
<table>

OK, il n’ya donc pas de solution générique à cause de la ré-étiquetage des attributs, mais vous obtenez ce que je veux dire, espérons-le. Je viens juste de commencer tous les trucs XSLT / XPATH, donc je vais y arriver à temps, mais tout indice serait utile.

Était-ce utile?

La solution

Je ne suis pas sûr à 100% de ce que vous essayez de faire, mais cette solution peut fonctionner si vos élément1, élément2 et élément3 sont imbriqués de manière cohérente.

<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 match="/">
        <table>
            <xsl:apply-templates select="//element3"></xsl:apply-templates>
        </table>
    </xsl:template>

    <xsl:template match="element3">
        <tr>
            <td><xsl:value-of select="../../@A"/></td>
            <td><xsl:value-of select="../../@B"/></td>
            <td><xsl:value-of select="../@C"/></td>
            <td><xsl:value-of select="../@D"/></td>
            <td><xsl:value-of select="@E"/></td>
            <td><xsl:value-of select="@F"/></td>
        </tr>
        <xsl:apply-templates select="*"></xsl:apply-templates>
    </xsl:template>

</xsl:stylesheet>

Autres conseils

J'avais besoin d'un XSLT similaire mais avec une profondeur inconnue, voici comment je l'ai fait.

Tout d'abord, ajoutez un wrapper pour la liste HTML table / def résultante et appelez le template mode = " puke " pour aplatir notre arbre XML:

<xsl:element name="div">
    <xsl:attribute name="class" select="puke" />
    <xsl:apply-templates select="$notice" mode="puke" />
</xsl:element>  

Nous associons ici chaque nœud pour afficher son contenu (par exemple, text ()) et ses attributs. Nous faisons cela récursivement. J'ai utilisé dl / dt / dd car mon arbre source était un arbre complexe qui ne peut pas être aplati en tant que.

<!-- @description: 
    Display all field from the notice so the customer can tell what he want
-->
<xsl:template match="node()" mode="puke">
<xsl:message>
    puking : <xsl:value-of select="local-name( . )" />
</xsl:message>
    <xsl:element name="dl">
        <xsl:element name="dt">
            <xsl:attribute name="class">tagName</xsl:attribute> 
            <xsl:value-of select="local-name( . )" />
        </xsl:element>
        <xsl:element name="dd">
            <xsl:attribute name="class">tagText</xsl:attribute>
            <xsl:value-of select="text()" /></xsl:element> 
        <xsl:element name="dl">
            <xsl:attribute name="class">attr</xsl:attribute>
            <!-- display attribute -->
            <xsl:apply-templates select="@*" />
        </xsl:element>
    </xsl:element>
    <!-- recursive call on node() -->
    <xsl:apply-templates select="./*" mode="puke" />    
</xsl:template>

Faites correspondre l'attribut d'un nœud donné et affichez-le.                                         
                                    

Le CSS utilise pour formater le code HTML résultant:

<style>
.puke {
    background-color: #BDD6DE;
    clear: both;
}
.tagName, .attrName {
    float: left;
}
.tagText, .attrText {
    clear: right;
}
</style>

Nous avons déjà un programme Pro * C en lecture dans une base de données Oracle, il appelle un script perl qui exécute à son tour une partie de Java pour extraire des données au format XML de la base de données susmentionnée pour appeler un fichier de commandes afin d’exécuter du traitement vbscript via FTP. à un autre serveur. J'espérais vraiment quelque chose à Fortran.

La question initiale doit être clarifiée:

  • Que se passe-t-il avec BValue et CValue dans la question initiale? Y a-t-il une raison pour laquelle ils ne devraient pas faire partie de la structure aplatie?
  • Tous les éléments de la doc XML ont-ils 2 attributs ou est-ce complètement arbitraire?
  • Y a-t-il seulement 3 types d'éléments et sont-ils toujours imbriqués comme indiqué dans l'exemple?
  • Votre élément1 peut-il être répété lui-même ou s'agit-il de l'élément racine de votre document?

Dans XSLT, il est possible d'écrire des transformateurs très génériques, mais il est souvent beaucoup plus facile d'écrire une feuille de style pour transformer un document lorsque vous pouvez prendre en compte les restrictions connues.

J'ai utilisé une version développée du modèle ci-dessous pour aplatir le XML structuré. Avertissement: il y avait du code spécifique à la casse dans la version originale (le XML est devenu au format CSV) que je viens de dépouiller et je n'ai pas testé cette version.

La façon dont cela fonctionne doit être clair: il imprime tout ce qui n’a pas d’enfants de noeud et appelle le modèle de manière récursive sur le noeud () qui a des enfants. Je ne pense pas qu'il gère correctement les attributs et les commentaires tel qu'il est actuellement, mais cela ne devrait pas être difficile à corriger.

<?xml version="1.0" encoding="UTF-8"?>

<!-- XSL template to flatten structured XML, before converting to CSV. -->
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" encoding="UTF-8"/>

    <xsl:strip-space elements="*" /> 

    <xsl:template match="/">
        <xsl:apply-templates select="//yourElementsToFlatten"/>
    </xsl:template>

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

    <xsl:template match="@*|node()">
        <xsl:choose>
            <!-- If the element has multiple childs, call this template 
                on its children to flatten it-->
            <xsl:when test="count(child::*) > 0">
                <xsl:apply-templates select="@*|node()"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:value-of select="text()" />
                </xsl:copy>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

</xsl:stylesheet>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top