2 votes

Sitemap en tant que structure de dossiers

Salut les gars, Je cherche un moyen d'afficher un plan du site sous forme de structure de dossiers.

Actuellement, le plan du site ressemble à ceci :

Mais à la place, je cherche ceci :

Existe-t-il un moyen pratique de le faire ?

Code du plan du site

...
<url>
  <loc>http://mydomain.com</loc>
  <changefreq>weekly</changefreq>
  <priority>1.00</priority>
</url>
<url>
  <loc>http://mydomain.com/category</loc>
  <changefreq>weekly</changefreq>
  <priority>0.80</priority>
</url>
...

** Code XSLT **

...
<ul> 
  <xsl:for-each select="xna:urlset/xna:url"> 
    <li><xsl:value-of select="xna:loc"/></li> 
  </xsl:for-each> 
</ul> 
...

0voto

Dimitre Novatchev Points 147842

I. Cette solution XSLT 1.0 :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common"
 exclude-result-prefixes="ext">

 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kLocByDomain" match="loc"
  use="word[1]"/>
 <xsl:key name="kLocByDomainAndCat" match="loc"
  use="concat(word[1], '+', word[2])"/>

 <xsl:key name="kLocByDomainCatProduct" match="loc"
  use="concat(word[1], '+', word[2], '+', word[3])"/>

 <xsl:template match="/*">
  <xsl:variable name="vrtfTokenized">
   <urls>
    <xsl:apply-templates/>
   </urls>
  </xsl:variable>

  <xsl:apply-templates mode="group"
   select="ext:node-set($vrtfTokenized)/*"/>
 </xsl:template>

 <xsl:template match="/*" mode="group">
  <h1>Sitemap</h1>

  <ul>
   <xsl:apply-templates mode="group" select=
    "loc[generate-id()
        =
         generate-id(key('kLocByDomain', word[1])[1])
        ]"/>
  </ul>
 </xsl:template>

 <xsl:template match="loc" mode="group">
  <li><xsl:value-of select="word[1]"/>
    <ul>
     <xsl:apply-templates mode="group2" select=
      "key('kLocByDomain', word[1])
             [generate-id()
             =
              generate-id(key('kLocByDomainAndCat',
                              concat(current()/word[1], '+', word[2])
                             )[1]
                          )
              ]"/>
    </ul>
  </li>
 </xsl:template>

 <xsl:template match="loc[word[2]]" mode="group2">
  <li><xsl:value-of select="word[2]"/>
    <ul>
     <xsl:apply-templates mode="group3" select=
      "key('kLocByDomainAndCat', concat(word[1], '+', word[2]))
             [generate-id()
             =
              generate-id(key('kLocByDomainCatProduct',
                              concat(current()/word[1], 
                                     '+', current()/word[2], 
                                     '+', word[3])
                             )[1]
                          )
              ]"/>
    </ul>
  </li>
 </xsl:template>

 <xsl:template match="loc[word[3]]" mode="group3">
  <li><xsl:value-of select="word[3]"/></li>
 </xsl:template>

 <xsl:template match="loc">
  <loc>
   <xsl:call-template name="tokenize">
    <xsl:with-param name="pText"
         select="substring-after(.,'http://')"/>
   </xsl:call-template>
  </loc>
 </xsl:template>

 <xsl:template name="tokenize">
  <xsl:param name="pText"/>

  <xsl:if test="string-length($pText)>0">
   <word>
    <xsl:value-of select=
     "substring-before(concat($pText,'/'), '/')"/>
   </word>
   <xsl:call-template name="tokenize">
    <xsl:with-param name="pText" select=
        "substring-after($pText,'/')"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>

 <xsl:template match="text()"/>
 <xsl:template match="text()" mode="group2"/>
 <xsl:template match="text()" mode="group3"/>
</xsl:stylesheet>

lorsqu'il est appliqué au document XML suivant (sur la base du fragment fourni) :

<site>
    <url>
        <loc>http://mydomain.com/</loc>
        <changefreq>weekly</changefreq>
        <priority>1.00</priority>
    </url>
    <url>
        <loc>http://mydomain.com/category</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
    <url>
        <loc>http://mydomain.com/category/product1</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
    <url>
        <loc>http://mydomain.com/category/product2</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
    <url>
        <loc>http://mydomain.com/other-category/product1</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
    <url>
        <loc>http://mydomain.com/other-category/product2</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
    <url>
        <loc>http://mydomain.com/other-category/product3</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
    <url>
        <loc>http://mydomain2.com/other-category/product3</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url> ...
</site>

produit le résultat voulu et correct :

    <h1>Sitemap</h1>
    <ul>
        <li>mydomain.com
            <ul>
                <li>category
                    <ul>
                        <li>product1</li>
                        <li>product2</li>
                    </ul></li>
                <li>other-category
                    <ul>
                        <li>product1</li>
                        <li>product2</li>
                        <li>product3</li>
                    </ul></li>
            </ul></li>
        <li>mydomain2.com
            <ul>
                <li>other-category
                    <ul>
                        <li>product3</li>
                    </ul></li>
            </ul></li>
    </ul>

--
et cela ressemble à ceci dans le navigateur :

Plan du site

  • mondomaine.com
    • catégorie
      • produit1
      • produit2
    • autre-catégorie
      • produit1
      • produit2
      • produit3
  • mondomaine2.com
    • autre-catégorie
      • produit3

Explication :

  1. Le plan du site englobe différents domaines, à l'intérieur desquels se trouvent différentes catégories et différents produits.

  2. Il s'agit d'une solution en deux temps.

  3. La première passe permet de tokeniser chaque url. Les tokens sont représentés par word éléments.

  4. La deuxième passe applique aux résultats de la première passe le regroupement muenchien sur des clés contenant une, puis deux, puis trois parties.

II. La solution XSLT 2.0

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <h1>Sitemap</h1>
  <ul>
   <xsl:for-each-group select="url/loc"
    group-by="tokenize(., '/')[3]"
   >
    <xsl:apply-templates select="."/>
   </xsl:for-each-group>
  </ul>
 </xsl:template>

 <xsl:template match="loc">
  <li><xsl:sequence select="tokenize(., '/')[3]"/>
   <ul>
    <xsl:for-each-group select=
     "current-group()[tokenize(., '/')[4]]"
     group-by="tokenize(., '/')[4]"
    >
     <xsl:apply-templates select="." mode="cat"/>
    </xsl:for-each-group>
   </ul>
  </li>
 </xsl:template>

 <xsl:template match="loc" mode="cat">
  <li><xsl:sequence select="tokenize(., '/')[4]"/>
   <ul>
    <xsl:for-each-group select=
     "current-group()[tokenize(., '/')[5]]"
     group-by="tokenize(., '/')[5]"
    >
     <xsl:apply-templates select="." mode="prod"/>
    </xsl:for-each-group>
   </ul>
  </li>
 </xsl:template>

 <xsl:template match="loc" mode="prod">
  <li><xsl:sequence select="tokenize(., '/')[5]"/></li>
 </xsl:template>
</xsl:stylesheet>

Explication :

Nous utilisons un certain nombre de fonctionnalités XSLT 2.0 qui facilitent le regroupement :

  1. <xsl:for-each-group>

  2. current-group()

0voto

empo Points 12803

Dans cette transformation 1.0, les catégories sont rassemblées en utilisant simplement la fonction substring-before y substring-after .

Pour appliquer cette transformation à votre cas, il vous suffit de définir votre domaine réel dans le fichier xsl:param et au sein de la xsl:key .

Notez que votre xml d'entrée est un fragment et qu'il n'est pas clair comment vous avez besoin de gérer le préfixe d'espace de nom. Par conséquent, j'ai testé la transformation sur un échantillon XML sans espaces de noms. Si votre XML source contient des préfixes d'espace de noms, la transformation devrait être ajustée.


XSLT 1.0 testé sous Saxon 6.5.5

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

    <xsl:param name="mydomain" select="'http://mydomain.com/'"/>
    <xsl:key name="urlbyloc" match="url" use="substring-before(substring-after(loc,'http://mydomain.com/'),'/')"/>

    <xsl:template match="/*">
        <ul>
            <li><xsl:value-of select="$mydomain"/>
                <ul>
                    <xsl:apply-templates select="url[generate-id()=generate-id(key('urlbyloc', substring-before(substring-after(loc,$mydomain),'/'))[1]) and position()!=1]"/>
                </ul>
            </li>
        </ul>
    </xsl:template>

    <xsl:template match="url">
        <li>
            <xsl:value-of select="key('urlbyloc', '')/loc[contains(text(),substring-before(substring-after(current()/loc,$mydomain),'/'))]"/>
            <ul>
                <xsl:apply-templates select="key('urlbyloc', substring-before(substring-after(loc,$mydomain),'/'))/loc"/>
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="loc">
        <li><xsl:value-of select="."/></li>
    </xsl:template>

    <xsl:template match="changefreq|priority"/>
</xsl:stylesheet>

Cette transformation est appliquée sur l'entrée suivante :

<url-set>
    <url>
        <loc>http://mydomain.com</loc>
        <changefreq>weekly</changefreq>
        <priority>1.00</priority>
    </url>
    <url>
        <loc>http://mydomain.com/category</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url>
    <url>
        <loc>http://mydomain.com/category/prod1</loc>
        <changefreq>weekly</changefreq>
        <priority>1.00</priority>
    </url>
    <url>
        <loc>http://mydomain.com/category/prod2</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url>
    <url>
        <loc>http://mydomain.com/othercat</loc>
        <changefreq>weekly</changefreq>
        <priority>1.00</priority>
    </url>
    <url>
        <loc>http://mydomain.com/othercat/prod1</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url>
    <url>
        <loc>http://mydomain.com/othercat/prod2</loc>
        <changefreq>weekly</changefreq>
        <priority>0.80</priority>
    </url>
</url-set>

Produit :

<ul>
   <li>http://mydomain.com/<ul>
         <li>http://mydomain.com/category<ul>
               <li>http://mydomain.com/category/prod1</li>
               <li>http://mydomain.com/category/prod2</li>
            </ul>
         </li>
         <li>http://mydomain.com/othercat<ul>
               <li>http://mydomain.com/othercat/prod1</li>
               <li>http://mydomain.com/othercat/prod2</li>
            </ul>
         </li>
      </ul>
   </li>
</ul>

En utilisant les fonctions définies par l'utilisateur de XSLT 2.0, nous pouvons rendre la transformation encore plus lisible. De plus, vous devrez indiquer votre domaine uniquement dans les paramètres initiaux, car 2.0 xsl:key supporte les références variables.

XSLT 2.0 testé sous Saxon-B 9.0.0.4J

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:empo="http://stackoverflow.com/users/253811/empo"
    exclude-result-prefixes="empo">
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:param name="mydomain" select="'http://mydomain.com/'"/>

    <xsl:function name="empo:get-category">
        <xsl:param name="loc"/>
        <xsl:param name="mydomain"/>
    <xsl:value-of select="substring-before(substring-after($loc,$mydomain),'/')"/>
  </xsl:function>

    <xsl:key name="urlbyloc" match="url" use="empo:get-category(loc,$mydomain)"/>

    <xsl:template match="/*">
        <ul>
            <li><xsl:value-of select="$mydomain"/>
                <ul>
                    <xsl:apply-templates select="url[generate-id()=generate-id(key('urlbyloc', empo:get-category(loc,$mydomain))[1]) and position()!=1]"/>
                </ul>
            </li>
        </ul>
    </xsl:template>

    <xsl:template match="url">
        <li>
            <xsl:value-of select="key('urlbyloc', '')/loc[contains(text(),empo:get-category(current()/loc,$mydomain))]"/>
            <ul>
                <xsl:apply-templates select="key('urlbyloc',empo:get-category(loc,$mydomain))/loc"/>
            </ul>
        </li>
    </xsl:template>

    <xsl:template match="loc">
        <li><xsl:value-of select="."/></li>
    </xsl:template>

    <xsl:template match="changefreq|priority"/>

</xsl:stylesheet>

0voto

Flynn1179 Points 6900

Voici un modèle simple qui devrait répondre à vos besoins :

  <xsl:template match="/">
    <xsl:apply-templates select="//url[1]" />
  </xsl:template>

  <xsl:template match="url">
    <xsl:param name="prefix" />
    <ul>
      <li><xsl:value-of select="substring-after(loc,$prefix)" /></li>
      <xsl:apply-templates select="../url[substring-after(loc,current()/loc) and not(contains(substring(substring-after(loc,current()/loc),2),'/'))]">
        <xsl:with-param name="prefix" select="concat(loc,'/')" />
      </xsl:apply-templates>
    </ul>
  </xsl:template>

Le premier modèle choisit simplement votre point de départ ; dans ce cas, il suppose que la première url du document contient votre racine. Utilisez n'importe quel xpath dont vous avez besoin ici ; //url[loc='http://mydomain.com'] ferait également l'affaire.

Le deuxième modèle fait le travail, en affichant simplement l'adresse actuelle de l'utilisateur. loc en supprimant ce qui le précède à l'aide de la fonction substring-after. Il s'applique ensuite à tout autre url les nœuds dont loc commence par le texte de la zone courante, mais n'a pas d'autre contenu. / des personnages.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X