3

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

Evert
  • 93,428
  • 18
  • 118
  • 189

2 Answers2

7

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

commonpike
  • 10,499
  • 4
  • 65
  • 58
6

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>
VolkerK
  • 95,432
  • 20
  • 163
  • 226
  • Not exactly what I'm looking for. In your example, the 'bar' and 'baz' elements might be implemented by completely different objects and methods who are not always aware of each other.. I __always__ want to specify the namespace, but I want it to only render the first time. – Evert Jun 16 '09 at 00:51
  • I haven't found any support for this in php/xmlwriter or libxml/xmlwriter. You probably have to keep track of this yourself. – VolkerK Jun 16 '09 at 11:12