[Xml-compile] minOccurs=0 and nillable="true" woes
Michael van der Westhuizen
michael.vanderwesthuizen at voss-solutions.com
Fri Nov 13 09:52:48 GMT 2009
Hi All,
I have a rather large vendor schema I need to interact with that makes
very heavy use of elements with both minOccurs=0 and
nillable="true" (138 instances of this combination).
I'm finding that the behavior of XML::Compile::Schema is a bit non-
intuitive in this case - the list archives suggest that this is a
known weakness, but unfortunately the default behavior is to produce
invalid XML documents (both syntactically and semantically), which is
definitely a problem for us. The problems we're seeing are in the
writer.
The first case, setting the data, works as expected.
The second case, setting the data to NIL, works as expected - we're
happy with this.
The third case, setting the data to undef works as expected, but
allows us to produce invalid XML documents (we can live with this,
since the code is just doing what we said).
The last case, not setting the data, behaves as the third case does,
which is a big problem for us.
I'd expect that when I do not send any data for a field which has
minOccurs=0 that no XML is generated for that element, irrespective of
the setting of nillable. Nillable, in this case, means something
completely different to "not present" (in the vendor schema "not
present" means leave as is, nil means set to nil - we need to do both).
I've appended a reduced schema and test cases that illustrate this
behavior.
Is there any chance of this being resolved? I'd hate to have to go
back to writing XML manually! I've poked around the Translate reader
and writer code and I can't find anywhere that looks suitable for a fix.
Michael
--- mike.xsd ---
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.visionoss.com/schema/UCMPROXY/1.0"
xmlns:tns="http://www.visionoss.com/schema/UCMPROXY/1.0"
elementFormDefault="qualified" version="1.0">
<xsd:complexType name="XDevice">
<xsd:sequence>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="devicePoolName" type="xsd:string"/>
<xsd:element name="someSortOfId" type="xsd:positiveInteger"
nillable="true" minOccurs="0"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="addDevice">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="newDevice" type="tns:XDevice"
nillable="false"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
--- end mike.xsd ---
--- test case ---
use XML::Compile::Schema ();
use XML::LibXML;
my $schema = XML::Compile::Schema->new('mike.xsd');
my $xdevice_writer = $schema->compile(WRITER => "{http://
www.visionoss.com/schema/UCMPROXY/1.0}addDevice");
my $doc = XML::LibXML::Document->new('1.0', 'UTF-8');
my $expected1 = '<x0:addDevice xmlns:x0="http://www.visionoss.com/schema/UCMPROXY/1.0
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"><x0:newDevice><x0:name>abc</
x0:name><x0:devicePoolName>devicepool1</
x0:devicePoolName><x0:someSortOfId xsi:nil="true"/></x0:newDevice></
x0:addDevice>';
my $hash = {newDevice => {name => 'abc', devicePoolName =>
'devicepool1', someSortOfId => 'NIL' }};
print sprintf("TEST 1: exists: %d, defined %d, value '%s'\n", exists
$hash->{newDevice}->{someSortOfId}, defined $hash->{newDevice}->
{someSortOfId}, $hash->{newDevice}->{someSortOfId});
my $node = $xdevice_writer->($doc, $hash);
my $s = $node->toString(0);
if ($s eq $expected1) {
print "optional, nillable, NIL OK\n";
} else {
print "optional, nillable, NIL FAIL\n";
}
my $expected2 = '<x0:addDevice xmlns:x0="http://www.visionoss.com/schema/UCMPROXY/1.0
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"><x0:newDevice><x0:name>abc</
x0:name><x0:devicePoolName>devicepool1</
x0:devicePoolName><x0:someSortOfId></x0:someSortOfId></x0:newDevice></
x0:addDevice>';
$hash = {newDevice => {name => 'abc', devicePoolName => 'devicepool1',
someSortOfId => undef }};
print sprintf("TEST 2: exists: %d, defined %d, value undef\n", exists
$hash->{newDevice}->{someSortOfId}, defined $hash->{newDevice}->
{someSortOfId});
$node = $xdevice_writer->($doc, $hash);
$s = $node->toString(0);
if ($s eq $expected2) {
print "optional, nillable, undef OK (invalid anyway, but that's
expected)\n";
} else {
print "optional, nillable, undef FAIL\n";
}
my $expected3 = '<x0:addDevice xmlns:x0="http://www.visionoss.com/schema/UCMPROXY/1.0
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance"><x0:newDevice><x0:name>abc</
x0:name><x0:devicePoolName>devicepool1</x0:devicePoolName></
x0:newDevice></x0:addDevice>';
$hash = {newDevice => {name => 'abc', devicePoolName =>
'devicepool1' }};
print sprintf("TEST 3: exists: %d, defined %d, value not present\n",
exists $hash->{newDevice}->{someSortOfId}, defined $hash->{newDevice}->
{someSortOfId});
$node = $xdevice_writer->($doc, $hash);
$s = $node->toString(0);
if ($s eq $expected3) {
print "optional, nillable, missing OK\n";
} else {
print "optional, nillable, missing FAIL (this one kills us)\n";
}
--- end test case ---
More information about the Xml-compile
mailing list