Here's an exaggerated example where a Personal Information schema (captured as personal.xsd) uses a flexible Contact schema. A contact can be an Address, Email, a specific online id, a phone number etc., I've provided a sample address.xsd and email.xsd. The Contact section of the Personal Information schema allows such content extension using the broader, "any" element, but still keeps the validations strict on purpose.
To test, create a temporary folder for the 5 files (2 .xml & 3 .xsd) I've provided below. I used C:\temp1 in my example, but alter the attached perl code to point to your path.
personal.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:per="urn:tempuri:Personal"
targetNamespace="urn:tempuri:Personal"
elementFormDefault="unqualified">
<element name="PersonalInfo">
<complexType>
<sequence>
<element name="FirstName" type="string"/>
<element name="LastName" type="string"/>
<element name="Contact" type="per:ContactType"/>
</sequence>
</complexType>
</element>
<complexType name="ContactType">
<sequence>
<any namespace="##other" processContents="strict"
maxOccurs="unbounded"/>
</sequence>
</complexType>
</schema>
address.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:Contact="urn:tempuri:Contact"
targetNamespace="urn:tempuri:Contact"
elementFormDefault="unqualified">
<xs:element name="Address">
<xs:complexType>
<xs:sequence>
<xs:element name="Street" type="xs:string"/>
<xs:element name="City" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
email.xsd
<?xml version="1.0" encoding="utf-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:Contact="urn:tempuri:Contact"
targetNamespace="urn:tempuri:Contact"
elementFormDefault="unqualified">
<xs:element name="Email">
<xs:complexType>
<xs:sequence>
<xs:element name="EmailAddress" type="xs:string"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
example1.xml
<?xml version="1.0" encoding="UTF-8"?>
<pinfo:PersonalInfo
xmlns:pinfo="urn:tempuri:Personal"
xmlns:cinfo="urn:tempuri:Contact"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:tempuri:Personal personal.xsd">
<FirstName>First Name</FirstName>
<LastName>Last Name</LastName>
<Contact>
<cinfo:Address
xsi:schemaLocation="urn:tempuri:Contact address.xsd">
<Street>Main Street</Street>
<City>Main City</City>
</cinfo:Address>
</Contact>
</pinfo:PersonalInfo>
example2.xml
<?xml version="1.0" encoding="UTF-8"?>
<pinfo:PersonalInfo
xmlns:pinfo="urn:tempuri:Personal"
xmlns:cinfo="urn:tempuri:Contact"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="urn:tempuri:Personal personal.xsd">
<FirstName>First Name</FirstName>
<LastName>Last Name</LastName>
<Contact>
<cinfo:Email xsi:schemaLocation="urn:tempuri:Contact email.xsd">
<EmailAddress>email1@test.org</EmailAddress>
</cinfo:Email>
</Contact>
</pinfo:PersonalInfo>
And finally the Perl code:
testExample.pl
#!/usr/bin/perl
package example;
use XML::LibXML;
use strict;
use warnings;
testExample1();
testExample2();
sub testExample1 {
my $schema = XML::LibXML::Schema->new(
location => "C:/temp1/personal.xsd"
);
my $document = XML::LibXML->load_xml(
location => "C:/temp1/example1.xml"
);
$schema->validate( $document );
}
sub testExample2 {
my $schema = XML::LibXML::Schema->new(
location => "C:/temp1/personal.xsd"
);
my $document = XML::LibXML->load_xml(
location => "C:/temp1/example2.xml"
);
$schema->validate( $document );
}
Hopefully, you'll see an error similar to the following for the 1st example:
C:/temp1/example1.xml:0: Schemas validity error :
Element '{urn:tempuri:Contact}Address':
No matching global element declaration available, but demanded
by the strict wildcard.
It's possible I'm missing an appropriate way to reference the contact namespace for the address and email schemas within the xml. There are other ways to successfully achieve validation, such as altering the personal.xsd file to statically import the other 2 schemas. Unfortunately, that won't be an option, unless I've mistyped/overlooked a schema definition nuance while creating the example.
Running the test outside Perl works correctly with strict validation turned on. I did have to add (with ease) those schemas programmatically though. If there's a similar way to import the Contact namespace of either schemas in Perl, right before the XML validation, it should solve the problem too.
|