2010-03-29 4 views
2

J'essaie de créer une page en utilisant les données de discogs.com (XML) -API. J'ai analysé avec simpleXML et ça fonctionne plutôt bien mais il y a certaines choses que je ne sais pas comment faire.Trier/Grouper des données XML avec PHP?

Voici une partie du XML:

<releases> 
    <release id="1468764" status="Accepted" type="Main"> 
    <title>Versions</title> 
    <format>12", EP</format> 
    <label>Not On Label</label> 
    <year>1999</year> 
    </release> 
    <release id="72246" status="Accepted" type="Main"> 
    <title>The M.O.F Blend</title> 
    <format>LP</format> 
    <label>Blenda Records</label> 
    <year>2002</year> 
    </release> 
    <release id="890064" status="Accepted" type="Main"> 
    <title>The M.O.F Blend</title> 
    <format>CD</format> 
    <label>Blenda Records</label> 
    <year>2002</year> 
    </release> 
    <release id="1563561" status="Accepted" type="TrackAppearance"> 
    <title>Ännu En Gång Vol. 3</title> 
    <trackinfo>Backtrack</trackinfo> 
    <format>Cass, Comp, Mix</format> 
    <label>Hemmalaget</label> 
    <year>2001</year> 
    </release> 
</releases> 

Ce que je veux réaliser quelque chose similair à la façon dont discogs présente les versions: http://www.discogs.com/artist/Mics+Of+Fury où les versions diférents du même communiqué sont classés ensemble. (Voir le mélange M.O.F dans mon lien) Ceci est fait sur les discogs avec une version principale qui présente les autres versions. malheureusement cette information n'est pas présente dans les données de l'API, donc je veux faire la même chose en regroupant les <release> -nodes avec les mêmes <title> -tags, ou ajouter un drapeau au <releases> qui n'ont pas un <title> unique? de bonnes idées sur la meilleure façon de le faire?

Je voudrais également savoir s'il est possible de compter les <release> -nodes (enfants de versions) qui ont le même attribut-type? comme dans cet exemple, comptez les versions avec le type "Main"?

peut-être qu'il est préférable de faire cela avec XMLReader ou XPath?

Répondre

0

J'ai récemment construit une classe que j'utilise pour créer et trier des tables HTML d'objets, voici quelques méthodes statiques qui pourraient vous être utiles pour trier des tableaux associatifs. J'ai supprimé la référence self :: de sorte que vous pouvez simplement utiliser les méthodes en tant que fonctions.

Utilisation: $array = array_sort($array, 'sort_key_name');

function array_sort(&$array) 
    { 
     if(!$array) return $keys; 
     $keys = func_get_args(); 
     array_shift($keys); 
     array_sort_func($keys); 
     usort($array,array("listview","array_sort_func")); 
     return $array; 
    } 


function array_sort_func($a, $b = NULL) 
    { 
     static $keys; 
     if($b === NULL) return $keys = $a; 

     foreach($keys as $k) 
     { 
      $aval = hod($a, '$a->' . $k); 
      $bval = hod($b, '$b->' . $k); 

      // modify string to compate 
      if(!is_numeric($aval)){$aval = strtolower($aval);} 
      if(!is_numeric($bval)){$bval = strtolower($bval);} 

      if($k[0]=='!') 
      { 
       $k=substr($k,1); 

       if($aval!== $bval) 
       { 
        if(is_numeric($aval) and is_numeric($bval)) 
        { 
         return $aval - $bval; 
        } 
        else 
        { 
         return strcmp($bval, $aval); 
        } 
       } 
      } 
      else if($aval !== $bval) 
      { 
       if(is_numeric($aval) and is_numeric($bval)) 
       { 
        $compare = $aval - $bval; 

        if($compare > 0) 
        { 
         return 1; 
        } 
        elseif($comare < 0) 
        { 
         return -1; 
        } 
       } 
       else 
       { 
        return strcmp($aval, $bval); 
       } 
      } 
     } 

     return 0; 
    } 

function hod(&$base, $path) 
    { 
     $licz = ''; 
     $keys = explode("->", $path); 
     $keys[0] = str_replace('$', '', $keys[0]); 
     $expression = '$ret = '; 
     $expression.= '$'; 

     foreach ($keys as $key) 
     { 
      if (++$licz == 1) 
      { 
       $expression.= 'base->'; 
      } 
      else 
      { 
       $expression.= $key.'->'; 
      } 
     } 

     $expression = substr($expression, 0, -2); 
     $expression.= ';'; 
     eval($expression); 
     return $ret; 
    } 
2

Vous pouvez utiliser xsl(t) et php's XSLTProcessor.
En xslt 2.0, vous pouvez utiliser quelque chose comme

<xsl:for-each-group select="release" group-by="title"> 

Malheureusement libxslt ne supporte pas (au moins la version utilisée dans la construction win32 php.net de php 5.3.2 ne fonctionne pas). Vous pouvez utiliser le Muenchian grouping method.

Test.xsl:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="html" version="4.0" encoding="utf-8" indent="yes"/> 

<xsl:key name="release-by-title" match="release" use="title" /> 

<xsl:template match="/"> 
    <html> 
    <head><title>...</title></head> 
    <body> 
     <xsl:apply-templates /> 
    </body> 
    </html> 
</xsl:template> 

<xsl:template match="releases"> 
    <table border="1"> 
    <xsl:for-each select="release[count(. | key('release-by-title', title)[1]) = 1]"> 
     <xsl:sort select="title" /> 
     <tr> 
     <th colspan="3"><xsl:value-of select="title" /></th> 
     </tr> 
     <xsl:for-each select="key('release-by-title', title)"> 
     <xsl:sort select="year" /> 
     <tr> 
      <td><xsl:value-of select="year" /></td> 
      <td><xsl:value-of select="label" /></td> 
      <td><xsl:value-of select="format" /></td> 
     </tr> 
     </xsl:for-each> 
    </xsl:for-each> 
    </table> 
</xsl:template> 

</xsl:stylesheet> 

test.xml contenant le document XML que vous avez fourni.
Et test.php:

<?php 
$doc = new DOMDocument; 
$doc->load('test.xsl'); 
$stylesheet = new XSLTProcessor; 
$stylesheet->importStyleSheet($doc); 
$doc->load('test.xml'); 

header('Content-type: text/html; charset=utf-8'); 
echo $stylesheet->transformToXML($doc); 

Et la sortie (onlye le <tableau> -partie) est:

<table border="1"> 
    <tr><th colspan="3">The M.O.F Blend</th></tr> 
    <tr> 
    <td>2002</td> 
    <td>Blenda Records</td> 
    <td>LP</td> 
    </tr> 
    <tr> 
    <td>2002</td> 
    <td>Blenda Records</td> 
    <td>CD</td> 
    </tr> 
    <tr><th colspan="3">Versions</th></tr> 
    <tr> 
    <td>1999</td> 
    <td>Not On Label</td> 
    <td>12", EP</td> 
    </tr> 
    <tr><th colspan="3">Ännu En Gång Vol. 3</th></tr> 
    <tr> 
    <td>2001</td> 
    <td>Hemmalaget</td> 
    <td>Cass, Comp, Mix</td> 
    </tr> 
</table> 

Maintenant, ce n'est pas beaucoup d'explication. Mais peut-être que cela vous donne des indices sur ce qu'il faut rechercher.

0

Je suppose que xslt 2.0 peut vous aider, voici la documentation pour appliquer le groupage et le tri sur des données XML en utilisant xsl 2.0: