Tracking namespace declarations with XMLWriter
-
13-09-2019 - |
Question
I'm working on an XML webservice (in PHP!), and in order to do things 'right', I want to use XMLWriter instead of just concatinating strings and hoping for the best.
I'm using XML namespaces everywhere using ->startElementNS and ->writeElementNS. The problem, is that every time I use these functions a new namespace declaration is also writting.
While this is correct syntax, it's a bit unneeded. I'd like to make sure my namespace declaration is only written the first time it's used in the context of a document.
Is there an easy way to go about this with XMLWriter, or am I stuck subclassing this and managing this manually.
Thanks, Evert
Solution
You can pass NULL as the uri parameter.
<?php
$w = new XMLWriter;
$w->openMemory();
$w->setIndent(true);
$w->startElementNS('foo', 'bar', 'http://whatever/foo');
$w->startElementNS('foo', 'baz', null);
$w->endElement();
$w->endElement();
echo $w->outputMemory();
prints<foo:bar xmlns:foo="http://whatever/foo"> <foo:baz/> </foo:bar>
OTHER TIPS
You can write out the namespace once in the desired location in the document, f.e. in the top element:
$writer = new XMLWriter();
$writer->openURI('php://output');
$writer->startDocument('1.0');
$writer->startElement('sample');
$writer->writeAttributeNS('xmlns','foo', null,'http://foo.org/ns/foo#');
$writer->writeAttributeNS('xmlns','bar', null, 'http://foo.org/ns/bar#');
$writer->writeElementNS('foo','quz', null,'stuff here');
$writer->writeElementNS('bar','quz', null,'stuff there');
$writer->endElement();
$writer->endDocument();
$writer->flush(true);
This should end up something like
<?xml version="1.0"?>
<sample xmlns:foo="http://foo.org/ns/foo#" xmlns:bar="http://foo.org/ns/bar#">
<foo:quz>stuff here</foo:quz>
<bar:quz>stuff there</bar:quz>
</sample>
It is sort of annoying xmlwriter doesnt keep track of those declarations - it allows you write invalid xml. It's also annoying the attribute is required, even if it can be null - and that its the third argument, not the last.
$2c, *-pike