Create XML with xmlns:xlink attribute in a node

2020-03-05 19:53发布

问题:

i'm trying to add generate an output like this:

<mets ....
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.loc.gov/METS/       
http://www.loc.gov/standards/mets/mets.xsd">

I can generate everything fine, but cannot add the xmlns:xlink attribute. The closest I get is:

$this->xml = new SimpleXMLElement('<mets></mets>');
$mets->addAttribute("xlink:someName", "blabla", "http://www.w3.org/1999/xlink");    
$mets->addAttribute("xsi:schemaLocation", "http://www.loc.gov/METS/  
http://www.loc.gov/standards/mets/mets.xsd",
"http://www.w3.org/2001/XMLSchema-instance");

Generates:

<mets ....
xmlns:xlink="http://www.w3.org/1999/xlink"
----begin of part I don't desire-----
xlink:someName="blablabla"
----end of  part I don't desire-----
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.loc.gov/METS/       
http://www.loc.gov/standards/mets/mets.xsd">

How can I add xmlns:xlink without adding xlink:somethingElse?

回答1:

The solution I've come up with is rather straight forward:

Because

$mets->addAttribute("xlink:someName", "", "http://www.w3.org/1999/xlink");

will always add two attributes - one for the namespace declaration (xmlns:xlink) and then the attribute you actually add (xlink:someName) - all you need to do is then to remove the unwanted added attribute and the prefix namespace attribute will remain:

unset($mets->attributes('xlink', true)['someName']);

Full example:

$mets = new SimpleXMLElement('<mets></mets>');
$mets->addAttribute("xlink:someName", "", "http://www.w3.org/1999/xlink");
unset($mets->attributes('xlink', true)['someName']);
echo $mets->asXML();

Output:

<?xml version="1.0"?>
<mets xmlns:xlink="http://www.w3.org/1999/xlink"/>

However this normally should not be necessary. You either need to use the namespace for something - then simplexml will add it when needed - or you don't need it, then there is no need to add it.

XML itself has no requirement at all to declare a namespace which is not used. Therefore you likely can leave it out as well or you only need to add it where you need to add it, e.g. the specific xlink element / attribute later on.

Any XML parser that supports namespaces will support any well-formed XML+Namspaces document, so there should really be no reason to worry whether or not the root element has that declaration and with which prefix. Simplexml just takes care of that, just add the xlink attribute where you need it. Example:

$mets = new SimpleXMLElement('<mets></mets>');
$child = $mets->addChild('child');
$child->addAttribute('xlink:href', 'child.xml', 'http://www.w3.org/1999/xlink');
$child = $child->addChild('child');
$child->addAttribute('xlink:href', 'child.xml', 'http://www.w3.org/1999/xlink');
echo $mets->asXML();

Output:

<?xml version="1.0"?>
<mets>
  <child xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="child.xml">
    <child xlink:href="child.xml"/>
  </child>
</mets>