2010-03-29 58 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: