Xpath - Comment obtenir le nom de tous les attributs existants des frères et sœurs


Tuckbros

Le but est simple. J'essaie de créer une table avec des attributs en colonnes.

Mon problème : Certains frères et sœurs n'ont pas les mêmes attributs que le premier. Lorsque je crée l'en-tête de table, je récupère le nom des attributs du premier nœud, puis j'espère que les attributs des frères et sœurs suivants seront les mêmes dans le même ordre. Ce n'est pas le cas. Je n'obtiens que des colonnes id, key, value, myattr1et l' myattr2attribut est placé dans la myattr1colonne.

Pour construire la table, je veux obtenir des colonnes : id, key, value, myattr1, myattr2

Comment puis-je récupérer la liste complète des attributs existants pour le nœud sur lequel je travaille et la parcourir en boucle ?

Je travaille toujours le même js et le même formulaire (voir lien en bas). Il nécessite désormais un bootstrap (css et js).

J'ai légèrement modifié le xml. C'est ici :

<?xml version="1.0" encoding="UTF-8"?>
<Domain>
  <Properties id="myid">
    <Property id="DOM00000" key="mykey1" value="value1" myattr2="Mail"/>
    <Property id="DOM00001" key="mykey2" value="value2" myattr1="EveryDay"/>
  </Properties>
  <Tokens>
    <Token name="token1" comment="" ><![CDATA[mydata1---blah-blah-blah]]></Token>
    <Token name="token2" comment="" ><![CDATA[mydata2---blah-blah-blah]]></Token>
  </Tokens>
  <Resources>
    <Resource name="res1" type="W" current="0">
      <Value><![CDATA[10]]></Value>
    </Resource>
    <Resource name="res2" type="W" current="0">
      <Value><![CDATA[10]]></Value>
    </Resource>
  </Resources>
</Domain>

L'état actuel du xsl :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/*">
    <xsl:element name="div">
        <xsl:attribute name="class">container</xsl:attribute>
        <ul class="nav nav-tabs">
            <xsl:for-each select="./*">
                <xsl:call-template name="tabs" />
            </xsl:for-each>
        </ul>
    </xsl:element>
    <xsl:element name="div">
    <xsl:attribute name="class">tab-content</xsl:attribute>
        <xsl:for-each select="./*">
                <xsl:call-template name="tabcontent" />
        </xsl:for-each> 
    </xsl:element>
</xsl:template>


<xsl:template name="tabs">
    <xsl:variable name="active">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="li">
        <xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
        <xsl:element name="a">
            <xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
            <xsl:attribute name="class">nav-link</xsl:attribute>
            <xsl:attribute name="data-toggle">tab</xsl:attribute>
            <xsl:value-of select="name(.)" />
        </xsl:element>

    </xsl:element>      
</xsl:template>

<xsl:template name="tabcontent">
    <xsl:variable name="activetab">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active in</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="div">
        <xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
        <xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
        <h3><xsl:value-of select="name(.)" /></h3>
        <table class="table table-striped table-hover">
            <thead>
                <tr><xsl:for-each select="./*[1]/@*"><th><xsl:value-of select="name(.)" /></th></xsl:for-each></tr>
            </thead>
            <tbody>
                <xsl:for-each select="./*"><tr>
                    <xsl:for-each select="./@*"><td><xsl:value-of select="." /></td></xsl:for-each></tr>
                </tr></xsl:for-each>
            </tbody>
        </table>
    </xsl:element>
</xsl:template>

</xsl:stylesheet> 

XSLT - Comment gérer CDATA en tant que contenu commun ?

Éditer :

Merci à la réponse de Tim-C Voici le xsl complet fonctionnant pour mon cas d'utilisation :

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:key name="attrs" match="/*/*/*/@*" use="concat(name(../..), '|', name())" />   

<xsl:template match="/*">
    <xsl:element name="div">
        <xsl:attribute name="class">container</xsl:attribute>
        <ul class="nav nav-tabs">
            <xsl:for-each select="./*">
                <xsl:call-template name="tabs" />
            </xsl:for-each>
        </ul>
    </xsl:element>
    <xsl:element name="div">
    <xsl:attribute name="class">tab-content</xsl:attribute>
        <xsl:for-each select="./*">
                <xsl:call-template name="tabcontent" />
        </xsl:for-each> 
    </xsl:element>
</xsl:template>


<xsl:template name="tabs">
    <xsl:variable name="active">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:element name="li">
        <xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
        <xsl:element name="a">
            <xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
            <xsl:attribute name="class">nav-link</xsl:attribute>
            <xsl:attribute name="data-toggle">tab</xsl:attribute>
            <xsl:value-of select="name(.)" />
        </xsl:element>

    </xsl:element>      
</xsl:template>

<xsl:template name="tabcontent">
    <xsl:variable name="activetab">
        <xsl:choose>
            <xsl:when test="preceding-sibling::*"></xsl:when>
            <xsl:otherwise>active in</xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="attrs" select="*/@*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
    <xsl:element name="div">
        <xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
        <xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
        <h3><xsl:value-of select="name(.)" /></h3>
        <table class="table table-striped table-hover">
        <thead>
            <tr>
                <xsl:for-each select="$attrs">
                <th>
                    <xsl:value-of select="name()" />
                </th>
                </xsl:for-each>
            </tr>
        </thead>
        <tbody>
            <xsl:for-each select="*">
            <tr>
                <xsl:variable name="current" select="." />
                <xsl:for-each select="$attrs">
                <td>
                    <xsl:value-of select="$current/@*[name() = name(current())]" />
                </td>
                </xsl:for-each>
            </tr>
            </xsl:for-each>
        </tbody>
  </table>
    </xsl:element>
</xsl:template>

<xsl:template name="toto"></xsl:template>




</xsl:stylesheet> 
Équipe C

Ce que vous utilisez ici est une technique appelée groupement de Muenchian pour obtenir une liste d'attributs distincts, en fonction de leur nom.

Cependant, bien que la question ne mentionne que id, key, value, myattr1, myattr2, qui sont les Propertyattributs, il semble que vous souhaitiez également le répéter pour les nœuds Tokenet Resource(c'est-à-dire que vous essayez d'être générique). Dans ce cas, vous définissez une clé comme ça, qui prend en compte le nom de l'élément principal

<xsl:key name="attrs" match="/*/*/*/@*" use="concat(name(../..), '|', name())" />

Ensuite, pour un élément donné (comme Properties) vous pouvez obtenir des attributs distincts comme ceci :

<xsl:variable name="attrs" select="*/@*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />

Cela peut ensuite être utilisé pour obtenir les en-têtes et accéder aux attributs pertinents pour chaque ligne.

Essayez ce XSLT (abrégé) :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />

<xsl:key name="attrs" match="/*/*/*/@*" use="concat(name(../..), '|', name())" />

<xsl:template match="/*">
  <xsl:for-each select="*">
    <xsl:call-template name="tabcontent" />
  </xsl:for-each> 
</xsl:template>

<xsl:template name="tabcontent">
  <xsl:variable name="attrs" select="*/@*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
  <table class="table table-striped table-hover">
    <thead>
      <tr>
        <xsl:for-each select="$attrs">
          <th>
            <xsl:value-of select="name()" />
          </th>
        </xsl:for-each>
      </tr>
    </thead>
    <tbody>
      <xsl:for-each select="*">
        <tr>
          <xsl:variable name="current" select="." />
          <xsl:for-each select="$attrs">
            <td>
              <xsl:value-of select="$current/@*[name() = name(current())]" />
            </td>
          </xsl:for-each>
        </tr>
      </xsl:for-each>
    </tbody>
  </table>
</xsl:template>
</xsl:stylesheet> 

Voyez-le en action sur http://xsltfiddle.liberty-development.net/jyRYYi7

Articles connexes


XPath :: Obtenir le suivi des frères et sœurs

ajouter des points-virgules J'ai la structure HTML suivante: J'essaie de créer une méthode robuste pour extraire le deuxième élément de résumé de couleur car il y aura beaucoup de ces balises dans le DOM. <table> <tbody> <tr bgcolor="#AAAAAA"> <tr>