获取包含大多数子项的SimpleXML对象的xml节点

时间:2013-08-26 10:55:52

标签: php xml parsing

使用以下代码片段,我使用php简单xml对象提取从xml检索节点而不是给定父节点我检索第一个子元素并将其转换为数组。我的问题:我希望得到孔子XML对象中具有大多数子元素的子元素,而不是目标应该转换为数组

/*
 * Retrive XML Nodes from Feed
 * 
 */

public function getXMLNodes() {
    $xml = simplexml_load_file($this->config[0]->link);
    switch (strtolower($this->config[0]->affiliate)) {
        case 'case1':
            $nodes = $xml->product[0]; //here stead of first object I should get that one which has most of chlidren
            break;
        case 'case2':
            $nodes = $xml->productItems->productItem[0];
            break;
        default :
            break;
    }
    $nodes = $this->xml2array($nodes);
    return $nodes;
}


/*
 * Convert Simple XML Object to array
 * 
 * @xml SimpleXMLObject
 * 
 */

function xml2array($xml) {
    $arr = array();
    foreach ($xml as $element) {
        $tag = $element->getName();
        $e = get_object_vars($element);
        if (!empty($e)) {
            $arr[$tag] = $element instanceof SimpleXMLElement ? $this->xml2array($element) : $e;
        } else {
            $arr[$tag] = trim($element);
        }
    }
    return $arr;
}

示例XML //在这种情况下,第二个拥有大部分子项

<?xml version="1.0" encoding="UTF-8"?>
<products>
    <product>
        <name></name>
        <productUrl></productUrl>
        <warranty/>
        <availability></availability>
        <inStock/>
        <shippingCost></shippingCost>
        <deliveryTime></deliveryTime>
        <weight/>
        <size/>
        <brand/>
        <model/>
        <ean/>
        <upc/>
        <isbn/>
        <condition></condition>
        <mpn/>
        <techSpecs/>
        <manufacturer></manufacturer>
        <programName></programName>
        <programLogoPath></programLogoPath>
        <programId></programId>
        <fields>
            <AlsoIncludes></AlsoIncludes>
            <Carrier></Carrier>
            <modelID></modelID>
            <Offertype></Offertype>
            <Processor></Processor>
            <Service></Service>
            <ShippingTax></ShippingTax>
            <StandardImage155x155></StandardImage155x155>
            <StandardImage200x200></StandardImage200x200>
            <Systemtype></Systemtype>
        </fields>
    </product>
    <product>
        <name></name>
        <productUrl></productUrl>
        <imageUrl></imageUrl>
        <description></description>
        <price></price>
        <currency></currency>
        <merchantCategoryName></merchantCategoryName>
        <sku></sku>
        <shortDescription/>
        <promoText/>
        <previousPrice></previousPrice>
        <warranty/>
        <availability></availability>
        <inStock/>
        <shippingCost></shippingCost>
        <deliveryTime></deliveryTime>
        <weight/>
        <size/>
        <brand/>
        <model/>
        <ean/>
        <upc/>
        <isbn/>
        <condition></condition>
        <mpn/>
        <techSpecs/>
        <manufacturer>Dell</manufacturer>
        <programName></programName>
        <programLogoPath></programLogoPath>
        <programId></programId>
        <fields>
            <AlsoIncludes></AlsoIncludes>
            <Carrier></Carrier>
            <modelID></modelID>
            <Offertype></Offertype>
            <Processor></Processor>
            <Service></Service>
            <ShippingTax></ShippingTax>
            <StandardImage155x155></StandardImage155x155>
            <StandardImage200x200></StandardImage200x200>
            <Systemtype></Systemtype>
        </fields>
    </product>
</products>

1 个答案:

答案 0 :(得分:1)

此方法/函数将找到具有大多数子节点的节点:

public function getNodeWithMostChildren($container)
{
    $countMax = 0;
    $nodeMax = null;
    foreach($container as $node) {
        $c = $node->count(); // get node count
        foreach ($node as $subnode) { // count subnode's children
            $c += $subnode->count();
        }
        if ($c > $countMax) { // is it larger than current maximum
            $countMax = $c; // set as new maximum
            $nodeMax = $node; // set node
        }
    }
    return $nodeMax;
}

这就是如何将它应用到你的代码中(这没有经过测试,但它应该有效):

public function getXMLNodes() {
    $xml = simplexml_load_file($this->config[0]->link);
    switch (strtolower($this->config[0]->affiliate)) {
        case 'case1':
            $nodes = $this->getNodeWithMostChildren($xml->product);
            break;
        case 'case2':
            $nodes = $this->getNodeWithMostChildren($xml->productItems->productItem);
            break;
        default :
            break;
    }
    $nodes = $this->xml2array($nodes);
    return $nodes;
}

//添加 我已经用你提供的xml测试了代码,这是结果(对我来说很好看 - 它包含节点名称和第二个<product>节点的值):

array(31) {
  ["name"]=>
  string(0) ""
  ["productUrl"]=>
  string(0) ""
  ["imageUrl"]=>
  string(0) ""
  ["description"]=>
  string(0) ""
  ["price"]=>
  string(0) ""
  ["currency"]=>
  string(0) ""
  ["merchantCategoryName"]=>
  string(0) ""
  ["sku"]=>
  string(0) ""
  ["shortDescription"]=>
  string(0) ""
  ["promoText"]=>
  string(0) ""
  ["previousPrice"]=>
  string(0) ""
  ["warranty"]=>
  string(0) ""
  ["availability"]=>
  string(0) ""
  ["inStock"]=>
  string(0) ""
  ["shippingCost"]=>
  string(0) ""
  ["deliveryTime"]=>
  string(0) ""
  ["weight"]=>
  string(0) ""
  ["size"]=>
  string(0) ""
  ["brand"]=>
  string(0) ""
  ["model"]=>
  string(0) ""
  ["ean"]=>
  string(0) ""
  ["upc"]=>
  string(0) ""
  ["isbn"]=>
  string(0) ""
  ["condition"]=>
  string(0) ""
  ["mpn"]=>
  string(0) ""
  ["techSpecs"]=>
  string(0) ""
  ["manufacturer"]=>
  string(4) "Dell"
  ["programName"]=>
  string(0) ""
  ["programLogoPath"]=>
  string(0) ""
  ["programId"]=>
  string(0) ""
  ["fields"]=>
  array(10) {
    ["AlsoIncludes"]=>
    string(0) ""
    ["Carrier"]=>
    string(0) ""
    ["modelID"]=>
    string(0) ""
    ["Offertype"]=>
    string(0) ""
    ["Processor"]=>
    string(0) ""
    ["Service"]=>
    string(0) ""
    ["ShippingTax"]=>
    string(0) ""
    ["StandardImage155x155"]=>
    string(0) ""
    ["StandardImage200x200"]=>
    string(0) ""
    ["Systemtype"]=>
    string(0) ""
  }
}