We recently discussed parsing XML with SimpleXML and since that writing I ran into a situation where I needed to parse a SOAP response. As it turns out, SOAP responses are a totally different beast when it comes to parsing them with SimpleXML. SOAP responses contain namespaces on some if not all of the nodes and SimpleXML doesn’t really care for that when using the traditional method of interaction. To accomplish this, you will need to use the SimpleXMLElement::children() method to specify the namespace:

// Mocks our SOAP response
$soap_response = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://phpave.com/api/">
	<SOAP-ENV:Body>
		<ns1:Posts>
			<ns1:Post>
				<ns1:Title>Parsing SOAP responses with SimpleXML</ns1:Title>
				<ns1:Description>Awesome post about parsing SOAP responses.</ns1:Description>
				<ns1:PostedDate>2014-07-13</ns1:PostedDate>
				<ns1:Author>
					<ns1:Name>Josh Sherman</ns1:Name>
					<ns1:Twitter>@joshtronic</ns1:Twitter>
				</ns1:Author>
				<ns1:Link>http://phpave.com/parsing-soap-responses-with-simplexml/</ns1:Link>
			</ns1:Post>
			<ns1:Post>
				<ns1:Title>How to parse XML with SimpleXML</ns1:Title>
				<ns1:Description>Awesome post about parsing XML.</ns1:Description>
				<ns1:PostedDate>2014-07-29</ns1:PostedDate>
				<ns1:Author>
					<ns1:Name>Josh Sherman</ns1:Name>
					<ns1:Twitter>@joshtronic</ns1:Twitter>
				</ns1:Author>
				<ns1:Link>http://phpave.com/how-to-parse-xml-with-simplexml/</ns1:Link>
			</ns1:Post>
		</ns1:Posts>
	</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
XML;

// Loads the XML
$xml = simplexml_load_string($soap_response);

// Grabs the posts
$posts = $xml->children('SOAP-ENV', true)->Body->children('ns1', true)->Posts->Post;

// Take the posts and generate some markup
foreach ($posts as $post)
{
	$twitter_url = 'https://twitter.com/' . $post->Author->Twitter;

	echo '
		<article>
			<h1>' . $post->Title . '</h1>
			<time>' . $post->PostedDate . '</time>
			<a href="' . $twitter_url . ' rel="author">' . $post->Author->Name . '</a>
			<p>' . $post->Description . '</p>
			<a href="' . $post->Link . '">Read Article</a>
		</article>
	';
}

Simply calling $xml->SOAP-ENV:Envelope will result in an error due to the fact that hyphens and colons are not valid characters for object variables or methods. Whenever you are entering a new namespace, you can use SimpleXMLElement::children() to define the name space. The second argument tells the method that you are defining a prefix and not a namespace URL.

Please note that the SimpleXMLElement::children() method will always return a SimpleXMLElement whether the node has any children or not.