Read XML child attributes PHP

I'm trying to access the child attributes of my XML.

This is my XML :

<csw:GetRecordByIdResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">
<csw:Record>
<dc:identifier xmlns:dc="http://purl.org/dc/elements/1.1/">8b511d58-5be8-4281-b932-5954dde667cd</dc:identifier>
<dc:title xmlns:dc="http://purl.org/dc/elements/1.1/">Temperature dalle stazioni meteorologiche siciliane</dc:title>
<dc:type xmlns:dc="http://purl.org/dc/elements/1.1/">dataset</dc:type>
<dc:subject xmlns:dc="http://purl.org/dc/elements/1.1/">temperatura</dc:subject>
<dc:subject xmlns:dc="http://purl.org/dc/elements/1.1/">sicilia</dc:subject>
<dc:subject xmlns:dc="http://purl.org/dc/elements/1.1/">environment</dc:subject>
<dct:abstract xmlns:dct="http://purl.org/dc/terms/">Dataset delle misurazioni effettuate dalle stazioni meteorologiche distribuite sul territorio della regione Sicilia in merito alla temperatura. Le misurazioni sono registrate con una frequenza di 5 minuti.</dct:abstract>
<dc:description xmlns:dc="http://purl.org/dc/elements/1.1/">Dataset delle misurazioni effettuate dalle stazioni meteorologiche distribuite sul territorio della regione Sicilia in merito alla temperatura. Le misurazioni sono registrate con una frequenza di 5 minuti.</dc:description>
<dc:rights xmlns:dc="http://purl.org/dc/elements/1.1/">copyright</dc:rights>
<dc:rights xmlns:dc="http://purl.org/dc/elements/1.1/">otherRestrictions</dc:rights>
<dc:language xmlns:dc="http://purl.org/dc/elements/1.1/">ita</dc:language>
<ows:BoundingBox xmlns:ows="http://www.opengis.net/ows" crs="urn:ogc:def:crs:EPSG:6.6:4326">
<ows:LowerCorner>15.5877 36.3799</ows:LowerCorner>
<ows:UpperCorner>11.5864 38.979</ows:UpperCorner>
</ows:BoundingBox>
<dc:URI xmlns:dc="http://purl.org/dc/elements/1.1/" protocol="OGC:WMS" name="Temperature stazioni siciliane 2015-05-01" description="Servizio di visualizzazione WMS">http://localhost:8080/geoserver/ewas/wms?service=WMS&version=1.1.0&request=GetMap&layers=ewas%3Adeg_temperature_2015_05_01&bbox=2246931.5%2C4058390.75%2C2574061.5%2C4269145.5&width=768&height=494&srs=EPSG%3A3004&styles=&format=application/openlayers</dc:URI>
<dc:URI xmlns:dc="http://purl.org/dc/elements/1.1/" protocol="OGC:WMS" name="Sicilia comuni confini">http://localhost:8080/geoserver/ewas/wms?service=WMS&version=1.1.0&request=GetMap&layers=ewas%3Asicilia_comuni&bbox=2244086.25%2C4054129.25%2C2578859.75%2C4297079.5&width=768&height=557&srs=EPSG%3A3004&styles=&format=application/openlayers</dc:URI>
</csw:Record>
</csw:GetRecordByIdResponse>

I'm currently access the children nodes using the following code in PHP:

$xml = simplexml_load_string($response);  
$parsercsw = $xml->children('csw', true);
$identifier = $parsercsw->Record->children('dc', true);
$json = json_encode($identifier);
$array = json_decode($json,TRUE);

in $response I have the XML above, then i use $parsercsw = $xml->children('csw', true); to first access the csw children node, then with $identifier = $parsercsw->Record->children('dc', true); I access to all dc nodes under csw:Record.

Finally with json_encode and json_decode I create my PHP array and then I can get all dc node values.

If I print the $array value I will get the following result:

print_r($array);
    Array
    (
    [identifier] => 8b511d58-5be8-4281-b932-5954dde667cd
    [title] => Temperature dalle stazioni meteorologiche siciliane
    [type] => dataset
    [subject] => Array
        (
            [0] => temperatura
            [1] => sicilia
            [2] => environment
        )

    [description] => Dataset delle misurazioni effettuate dalle stazioni meteorologiche distribuite sul 
  territorio della regione Sicilia in merito alla temperatura. Le misurazioni sono registrate con una frequenza di 5 minuti.
    [rights] => Array
        (
            [0] => copyright
            [1] => otherRestrictions
        )

    [language] => ita
    [URI] => Array
        (
            [0] => http://localhost:8080/geoserver/eWAS/wms?service=WMS&version=1.1.0&request=GetMap&layers=eWAS%3Adeg_temperature_2015_05_01&bbox=2246931.5%2C4058390.75%2C2574061.5%2C4269145.5&width=768&height=494&srs=EPSG%3A3004&styles=&format=application/openlayers
            [1] => http://localhost:8080/geoserver/eWAS/wms?service=WMS&version=1.1.0&request=GetMap&layers=eWAS%3Asicilia_comuni_confini&bbox=2244086.25%2C4054129.25%2C2578859.75%2C4297079.5&width=768&height=557&srs=EPSG%3A3004&styles=&format=application/openlayers
        )

)

In this way I can access all the values I need, with :

$uri = $array["URI"];

My problem is that i want to read also the attributes "name" of dc:URI in the XML, but i can't find out how to do that, i tried different methods but no one works. Can someone please help me? Thanks

Answer

Solution:

This is where you're going wrong:

Finally with json_encode and json_decode I create my PHP array...

You don't want a PHP array, you want an object that lets you access the XML - which you already have! Delete that horrible json_encode/json_decode hack, and read the examples in the manual and this reference question.

Here's some example code (with simplified XML to save space, and because what you posted wasn't valid XML).

$response = <<<EOF
<csw:GetRecordByIdResponse xmlns:csw="http://www.opengis.net/cat/csw/2.0.2">
<csw:Record>
<dc:identifier xmlns:dc="http://purl.org/dc/elements/1.1/">8b511d58-5be8-4281-b932-5954dde667cd</dc:identifier>
<dc:URI xmlns:dc="http://purl.org/dc/elements/1.1/" protocol="OGC:WMS" name="Temperature stazioni siciliane 2015-05-01" description="Servizio di visualizzazione WMS">https://example.com/first-link</dc:URI>
<dc:URI xmlns:dc="http://purl.org/dc/elements/1.1/" protocol="OGC:WMS" name="Sicilia comuni confini">https://example.com/second-link</dc:URI>
</csw:Record>
</csw:GetRecordByIdResponse>
EOF;


// Define your own names for namespaces, don't rely on remote XML always assigning the same prefixes
const XMLNS_CSW = 'http://www.opengis.net/cat/csw/2.0.2';
const XMLNS_DC = 'http://purl.org/dc/elements/1.1/';

$xml = simplexml_load_string($response);  

$parsercsw = $xml->children(XMLNS_CSW);
// You'd called this variable $identifier, but it's actually all the elements in that namespace
$dcElements = $parsercsw->Record->children(XMLNS_DC);
// This is how you'd get the identifier element
$identifier = $dcElements->identifier;

// Loop over the URI elements, as objects
foreach ( $dcElements->URI as $uriElement ) {
    // Get the string content with (string)
    $uri = (string)$uriElement;
    // Attributes with no prefix technically aren't in any namespace (blame the authors of the XML namespace spec)
    // So we need to select the namespace with an empty name
    $attributesWithNoNamespace = $uriElement->attributes(null);
    // Now we can access them with either ['foo'] or ->foo syntax, remembering to cast to string rather than object
    $name = (string)$attributesWithNoNamespace['name'];
    
    echo "The URI named '$name' is '$uri'\n";
}

Source