I am currently working on a PHP class to manipulate SVG documents, using PHP’s SimpleXML to handle the XML structure. I found myself needing to reset the namespaced attribute “xlink:href” in the following XML block:
<image y="35.811729" x="35.60614" id="image2886" height="581.58026" width="670.37695" xlink:href="file:///home/jon/Documents/LeafletGen/test.png" />
Finding the necessary info proved somewhat difficult, so I’m recording it here for posterity. Firstly, note that obtaining namespaced attributes via attributes() cannot be done via the default namespace:
$xml = '<image y="35.811729" x="35.60614" id="image2886" height="581.58026" width="670.37695" xlink:href="file:///home/jon/Documents/LeafletGen/test.png" />'; $xmlDoc = new SimpleXMLElement($xml); $attribs = $xmlDoc->attributes(); $attribsNamespace = $xmlDoc->attributes('http://www.w3.org/1999/xlink'); print_r($attribs); print_r($attribsNamespace);
This code returns the following results:
SimpleXMLElement Object ( [@attributes] => Array ( [y] => 35.811729 [x] => 35.60614 [id] => image2886 [height] => 581.58026 [width] => 670.37695 ) ) SimpleXMLElement Object ( [@attributes] => Array ( [href] => file:///home/jon/Documents/LeafletGen/test.png ) )
That illustrates that namespaced items are treated separately. OK, so let’s try setting and unsetting ordinary elements:
// $xml as previously $xmlDoc = new SimpleXMLElement($xml); unset($xmlDoc['x']); $xmlDoc['y'] = "1234"; echo $xmlDoc->asXML();
This returns the result as expected – the “x” attribute is removed and the “y” attribute is reset:
<image y="1234" id="image2886" height="581.58026" width="670.37695" xlink:href="file:///home/jon/Documents/LeafletGen/test.png" />
However, this is not possible with attributes that have a namespace. If we add in an attribute using the array syntax, it replicates the existing attribute:
// $xml as previously $xmlDoc = new SimpleXMLElement($xml); $xmlDoc['xlink:href'] = "file:///home/jon/Documents/LeafletGen/new-image.png"; echo $xmlDoc->asXML();
Result:
<image y="35.811729" x="35.60614" id="image2886" height="581.58026" width="670.37695" xlink:href="file:///home/jon/Documents/LeafletGen/test.png" xlink:href="file:///home/jon/Documents/LeafletGen/new-image.png" />
Clearly, this is not what we want. Furthermore, unsetting using the array syntax doesn’t work either. The solution is to unset the attribute inside a SimpleXMLElement, then set it, either using the array syntax as before, or using the addAttribute method:
// $xml as previously $xmlDoc = new SimpleXMLElement($xml); $attribs = $xmlDoc->attributes( $ns = 'http://www.w3.org/1999/xlink' ); $newVal = 'file:///home/jon/Documents/LeafletGen/new-image.png'; unset($attribs->href); $xmlDoc->addAttribute( 'xlink:href', $newVal, $ns ); // This seems to work too, but the attribute is probably // not 'understood' by SimpleXML //$xmlDoc['xlink:href'] = $newVal; echo $xmlDoc->asXML();
And voila:
<image y="35.811729" x="35.60614" id="image2886" height="581.58026" width="670.37695" xlink:href="file:///home/jon/Documents/LeafletGen/new-image.png" />