使用PHP解析XML并获取嵌套的级元素值和属性值

Hello i am trying to parse xml i have couple of trouble do this.

I am not able to get nested level element.For eg.telephone I am not able to get attribute value.I am not able to get and the third level nested element properly, i tried many code for that also for attribute values of some elements. like here telephone type and commercialListingType

Here is my xml

    <propertyList date="2014-06-02-17:30:33" username="bad" password="dfdfd">

    <business modTime="2014-06-02-12:22:32" status="current">

    <agentID>TEST</agentID>

    <uniqueID>1420648</uniqueID>

    <listingAgent id="1">

    <name>hjon Smith</name>

    <telephone type="BH"></telephone>

    <telephone type="mobile"></telephone>

    <email>bbd@ozemail.com.au</email>

    </listingAgent><listingAgent id="2"></listingAgent>

    <address display="no">

    <subNumber>Yoghurt bbd 4000</subNumber>

    <streetNumber></streetNumber>

    <street></street>

    <suburb display="no">Newy</suburb>

    <state>NSW</state>

    <postcode>2000</postcode>

    <country>London</country>

    </address>

    <price display="yes" plusSAV="no" tax="exclusive">200000</price>

    <priceView></priceView>


    <externalLink href=""/><externalLink href=""/>

    <videoLink href=""/>

    <underOffer value="no"/>

    <commercialListingType value="sale"/>

    <franchise value="yes"/>

    <businessCategory id="1">

    <name>Franchise</name>

    </businessCategory>
    </propertyList>

Here is my code

<?php
$xml=simplexml_load_file("testing.xml");

$data = array();



foreach($xml->business as $business) {


    $business = (array) $business;


    if (!array_key_exists($business['uniqueID'], $data)) {

        $listingAgent = (array) $business['listingAgent'];
        $price = (array) $business['price'];
        $commercialListingType= (array)$business['commercialListingType'];

        print_r($commercialListingType->attributes());

        $data[$business['uniqueID']] = array(
            'agentID' => $business['agentID'],
            'uniqueID' => $business['uniqueID'],
            'name' => (string)$listingAgent[0]->name,
            'email' => (string) $listingAgent[0]->email,
            'price'=>(string) $price[0],
            'telephone' => (string) $listingAgent[0]->telephone[0],
            'mobile' => (string) $listingAgent[0]->telephone[1],
        );
    }



}

echo "<pre>";
print_r($data);

?>  
$xml = new SimpleXMLElement($string); //variable $string is nothing but your XML content
$result = $xml->xpath('/propertyList/business/listingAgent/telephone');
//short form
//$result = $xml->xpath('////telephone');
foreach($result as $node) {
  print 'Telephone Atrribute: '.$node->attributes().'<br>';
}

The problem you have is in this line:

$commercialListingType = (array)$business['commercialListingType'];

As $commercialListingType is a SimpleXMLElement you don't need to cast it to an array - it allows to access anything you need already via it's standard object and array-access notations. Casting to an array will reduce the functionality with the risk to break it.

And that is what is exactly happening here in your case on the next line:

print_r($commercialListingType->attributes());

Give you the famous

Fatal error: Call to a member function attributes() on a non-object

error, as you told PHP to make $commercialListingType an array - which is not an object in PHP.

So better understand that with SimpleXMLElement, there is no need to cast to array:

$data = array();

foreach ($xml->business as $business)
{
    $uniqueID = (string)$business->uniqueID;

    if (isset($data[$uniqueID])) {
        continue;
    }

    $listingAgent          = $business->listingAgent;
    $price                 = $business->price;
    $commercialListingType = $business->commercialListingType;

    $data[$uniqueID] = array(
        'agentID'   => (string) $business->agentID,
        'uniqueID'  => $uniqueID,
        'name'      => (string)$listingAgent->name,
        'email'     => (string)$listingAgent->email,
        'price'     => (string)$price,
        'telephone' => (string)$listingAgent->telephone,
        'mobile'    => (string)$listingAgent->telephone[1],
    );
}

You find more usage examples in the PHP manual: http://www.php.net//manual/en/simplexml.examples-basic.php

This will also explain to you how to access attributes.

So remember: It is a fault casting to array with SimpleXML. Whoever told you to do that and said to you it would make things more easy, was not telling you the whole story.

Exemplary output:

Array
(
    [1420648] => Array
        (
            [agentID] => TEST
            [uniqueID] => 1420648
            [name] => hjon Smith
            [email] => bbd@ozemail.com.au
            [price] => 200000
            [telephone] => 
            [mobile] => 
        )

)

Demo online: https://eval.in/159675 ; Full Code:

<?php 
/**
 * @link http://stackoverflow.com/a/24096869/367456
 */ 
ob_start(); 
?>
    <propertyList date="2014-06-02-17:30:33" username="bad" password="dfdfd">
        <business modTime="2014-06-02-12:22:32" status="current">
            <agentID>TEST</agentID>
            <uniqueID>1420648</uniqueID>
            <listingAgent id="1">
                <name>hjon Smith</name>
                <telephone type="BH"></telephone>
                <telephone type="mobile"></telephone>
                <email>bbd@ozemail.com.au</email>
            </listingAgent>
            <listingAgent id="2"></listingAgent>
            <address display="no">
                <subNumber>Yoghurt bbd 4000</subNumber>
                <streetNumber></streetNumber>
                <street></street>
                <suburb display="no">Newy</suburb>
                <state>NSW</state>
                <postcode>2000</postcode>
                <country>London</country>
            </address>
            <price display="yes" plusSAV="no" tax="exclusive">200000</price>
            <priceView></priceView>
            <externalLink href=""/>
            <externalLink href=""/>
            <videoLink href=""/>
            <underOffer value="no"/>
            <commercialListingType value="sale"/>
            <franchise value="yes"/>
            <businessCategory id="1">
                <name>Franchise</name>
            </businessCategory>
        </business>
    </propertyList>
<?php
/**
 */
$xml = simplexml_load_string(ob_get_clean());

$data = array();

foreach ($xml->business as $business)
{
    $uniqueID = (string)$business->uniqueID;

    if (isset($data[$uniqueID])) {
        continue;
    }

    $listingAgent          = $business->listingAgent;
    $price                 = $business->price;
    $commercialListingType = $business->commercialListingType;

    $data[$uniqueID] = array(
        'agentID'   => (string) $business->agentID,
        'uniqueID'  => $uniqueID,
        'name'      => (string)$listingAgent->name,
        'email'     => (string)$listingAgent->email,
        'price'     => (string)$price,
        'telephone' => (string)$listingAgent->telephone,
        'mobile'    => (string)$listingAgent->telephone[1],
    );
}

print_r($data);