2010-03-29 93 views
2

我正在嘗試使用來自discogs.com(XML)-API的數據製作頁面。我一直在用simpleXML解析它,它工作得很好,但有些事情我不知道該怎麼做。使用PHP對XML數據進行排序/分組?

這裏是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> 

什麼我想要實現的東西similair到discogs如何呈現的版本:http://www.discogs.com/artist/Mics+Of+Fury在同一發行版diferent版本排序在一起。 (請參見我的鏈接中的M.O.F Blend)這是在discogs上完成的,其主版本具有其他版本。可惜這種信息不存在於API數據,所以我想用相同的<title>標籤都有效分組的<release> -nodes做同樣的事情,或添加標記到<releases>不具有唯一<title>?任何好的想法在這樣做的最好方法?

我也想知道是否有可能算<release> -nodes(發佈兒童)具有相同類型屬性?就像在這個例子中計算類型爲「Main」的版本一樣?

也許這是更好地做這個事情的XMLReader或XPath?

回答

0

我最近建立了一個類我用來創建和分選對象的HTML表格,這裏是從它的一些靜態方法你會發現排序關聯數組有用。我已經刪除了self :: reference,所以你可以使用這些方法作爲函數。

用法:$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

您可以使用xsl(t)php's XSLTProcessor
在XSLT 2.0中,您可以使用類似

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

可惜libxslt不支持這一(在PHP 5.3.2沒有的php.net win32的構建至少使用的版本)。
但是你可以使用Muenchian grouping method

test.xsl:包含您所提供的XML文檔

<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。
而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); 

和輸出(onlye的<表>雙組分)是:

<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> 

現在,沒有太多的交代的。但也許它會給你一些提示,以尋找什麼。

0

我猜XSLT 2.0也許能夠幫助你,這裏是爲應用分組和使用XSL 2 XML數據分類的文檔。0: