使用PHP解析XML以创建包含数据表的层次结构的更好方法

时间:2013-04-03 21:26:34

标签: php xml-parsing

我最近(2周前)开始用PHP编码,今天我遇到了一个问题,想知道是否有人可以帮助/指导我。

我从Web服务获取xml数据,并希望呈现如下图所示的数据

enter image description here

获取的XML看起来像这样

 <pricesheets>
<pricesheet>            
    <buyinggroupname>China</buyinggroupname>
    <categoryname>Category B</categoryname>
    <currency>USD</currency>
    <discamt>39330.00</discamt>
    <productdesc>Product B description</productdesc>
    <prdouctId> Product B </productId>
</pricesheet>
<pricesheet>            
    <buyinggroupname>Asia</buyinggroupname>
    <categoryname>Category A</categoryname>
    <currency>USD</currency>
    <discamt>39330.00</discamt>
    <productdesc>Product A description</productdesc>
    <prodouctId> Product A </productId>
</pricesheet>   
</pricesheets>

我遇到的问题是解析XML以上的最佳方法,以便我可以根据'purchasegroupname'和'categoryname'呈现产品。一旦我知道如何渲染数据,我就可以轻松完成折叠和扩展功能。

以下是我为实现目标所做的工作。但我确信我的代码不是高效且可扩展的。

$xmldata;  // XML return by the webservice
$data = simplexml_load_string($xmldata);
$category_A_items = '';
$category_B_items = '';
foreach ($data as $object) {
  if($object->categoryname == 'Category A') { // Bad Idea : Hard coded category
      $category_A_items .= '<tr><td>'.$object->prdouctId.'</td><td>'. $object->productdesc. '</td><td>'. $object->discamt. '</td></tr>';
    }
  elseif($object->CATEGORYNAME == 'Category B') { // Bad Idea : Hard coded category
        $category_B_items .='<tr><td>'.$object->prdouctId. '</td><td>'. $object->productdesc. '</td><td>'. $object->discamt. '</td></tr>';                      
    }
}
//Render Category A items in table
 if(strlen($category_A_items) > 0) {
      echo '<h3>CAD</h3>';
      echo '<table><tr><th>Product Name</th><th>Description</th><th>Price</th></tr>';
      echo $cadItems;
      echo '</table>'. PHP_EOL;
  }
  //Render Category B items in table
  if(strlen($category_B_items) > 0) {
      echo '<h3>Breast Biopsy</h3>';
      echo '<table><tr><th>Product Name</th><th>Description</th><th>Price</th></tr>';
      echo $breastBiopsy;
      echo '</table>'. PHP_EOL;
  }

以上代码仅根据类别(硬编码)呈现数据。现在有什么更好的方法来做同样的事情,这样我就可以基于'buyingroupname'和'categoryname'来呈现数据而无需在php代码中对这两个值中的任何一个进行硬编码。

提前致谢!

2 个答案:

答案 0 :(得分:1)

获取一个具有xpath的唯一<categoryname> - 节点数组,然后遍历它并选择所有<pricesheet> - 具有该特定类别的节点,让xpath再次执行该作业:

$xml = simplexml_load_string($x);
$cat = array_unique($xml->xpath("//categoryname"));

foreach ($cat as $c) {
    echo "$c<br />";
    foreach ($xml->xpath("//pricesheet[categoryname='$c']") as $p) {
        echo $p->productId."<br />";
    }
}

观看现场演示@ http://codepad.viper-7.com/m9ruRU

当然,您必须添加用于创建表的代码...

答案 1 :(得分:0)

将字符串放在带有变量键的数组中,可以让PHP为您组织它们,而您根本不需要知道任何类别名称。我使用了多维数组,以便每个购买群在其中都有自己的类别。然后循环遍历数组以生成每个表。如果您需要更多解释,请告诉我。我第一次看到它时误解了你的形象。

$xmldata;  // XML return by the webservice
$data = simplexml_load_string($xmldata);
$buyinggroups = array();
foreach ($data as $object) {
    if(isset($object->buyinggroupname) || isset($object->BUYINGGROUPNAME)) {
        if(isset($object->buyinggroupname)) {
            $name = $object->buyinggroupname;
        } else {
            $name = $object->BUYINGGROUPNAME;
        }
    }
    if(isset($object->categoryname) || isset($object->CATEGORYNAME)) {
        if(isset($object->categoryname)) {
            $category = $object->categoryname;
        } else {
            $category = $object->CATEGORYNAME;
        }
    }
    if(isset($category) && isset($name)) { //just making sure this row is OK
        if(!isset($buyinggroups[$name])) {
            $buyinggroups[$name] = array();  //initialize the outer array
        }
        if(!isset($buyinggroups[$name][$category])) {
            $buyinggroups[$name][$category] = '';  //this is like your previous $category_A_items
        }
        $buyinggroups[$name][$category] .= '<tr><td>'.$object->productId.'</td><td>'. $object->productdesc. '</td><td>'. $object->discamt. '</td></tr>';
    }
}


//Render all categories in lots of tables
//I am guessing at what HTML you want here; I don't think it's necessarily correct
echo '<table>'. PHP_EOL;
foreach($buyinggroups as $name=>$set) {
    echo '<tr><th colspan="2">'.$name.'</th></tr>'. PHP_EOL;
    echo '<tr><th> </th><td>';
    foreach($set as $category=>$rows) {
        echo '<table>'; 
        echo '<tr><th><h3>'.$category.'</h3></th>'. PHP_EOL;
        echo '<td><table><tr><th>Product Name</th><th>Description</th><th>Price</th></tr>';
        echo $rows;
        echo '</table>'. PHP_EOL;
    }
    echo '</td></tr>';
}
echo '</table>';

修改

这不可能超出您的调试能力。您正在获得调试所需的一切。 PHP告诉你行号和错误。你谷歌错误,找出它的意思。然后你去那个行号,看看那里有什么对应你用Google搜索的东西。在这种情况下,我可以告诉你“非法偏移类型”意味着你有一个不是字符串或整数的数组键。在错误消息中的那些行上,您有数组键$ name和$ category。尝试var_dump($ name)和var_dump($ category)来找出它们实际是什么,甚至var_dump($ object)来找出如何从对象中获取名称和类别。