Here we have a simple XML schema:
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="item">
<xs:complexType>
<xs:sequence>
<xs:element ref="item" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
<xs:attribute name="is-foo" type="xs:boolean" default="true" use="optional" />
<xs:attribute name="is-bar" type="xs:boolean" default="false" use="optional" />
</xs:complexType>
</xs:element>
</xs:schema>
Just recursive <item>
nodes with optional is-foo
/is-bar
boolean attributes, defaulting to true
and false
respectively.
Now, how are these default values useful, in the context of reading XML data in PHP? If I have a valid XML document:
<item is-foo="false" is-bar="false">
<item is-bar="true">
<item>
<item is-foo="true">
<item />
<item is-foo="true" />
</item>
</item>
<item is-foo="true" is-bar="true" />
</item>
</item>
Against which I run:
$document = new DOMDocument();
$document->load('./test.xml');
var_dump($document->schemaValidate('./test.xsd'));
$xpath = new DOMXPath($document);
foreach ($xpath->query('//item') as $item) {
echo $item->getNodePath() . PHP_EOL
. ' is-foo : ' . $item->getAttribute('is-foo') . PHP_EOL
. ' is-bar : ' . $item->getAttribute('is-bar') . PHP_EOL;
}
I get the following output (which, while expected, is unfortunate):
bool(true)
/item
is-foo : false
is-bar : false
/item/item
is-foo :
is-bar : true
/item/item/item[1]
is-foo :
is-bar :
/item/item/item[1]/item
is-foo : true
is-bar :
/item/item/item[1]/item/item[1]
is-foo :
is-bar :
/item/item/item[1]/item/item[2]
is-foo : true
is-bar :
/item/item/item[2]
is-foo : true
is-bar : true
The issue here being all of the empty attribute values.
Aside from programatically injecting default values into the documents (which would require interpreting the schema for any reusability) are there any options to transform an XML document to include default values as defined in the corresponding schema?
This is not currently possible with the DOM extension.
libxml doesn't do this unless the XML_SCHEMA_VAL_VC_I_CREATE
is set on the schema validation context in use, and currently it isn't.
I've created a patch that should hopefully expose this functionality by means of an additional $flags
argument to schemaValidate()
/schemaValidateSource()
and an new LIBXML_SCHEMA_CREATE
constant (example target code), but I've yet to test it as I don't have a usable build environment readily available.
EDIT
The patch has now been tested and I've created a PR to merge into the 5.5 branch.
EDIT 2
The PR has now been merged into master and the feature should be available from PHP 5.5.2.
EDIT 3