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" />