Groups | Blog | Home
all groups > dotnet xml > july 2004 >

dotnet xml : Multiple schemas, one xml doc


anonymous NO[at]SPAM coolgroups.com
7/14/2004 5:57:20 PM
When I use the schema collection to apply many schemas to
one XML instance document, I get an error if I do not
qualify every element with the appropriate namespace.

Both the W3C site and this article
(http://www.xfront.com/ZeroOneOrManyNamespaces.html) imply
that I can submit an XML instance without having to
qualify each element.

How do I accomplish this while still using .Net & the
Validating Reader?

Thanks,

Raj (Example code follows)
rajS*P*A*Mmuchhala@yahoo.com

Example:

XSD Product
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.product.org"
xmlns="http://www.product.org"
elementFormDefault="unqualified">
<xsd:complexType name="ProductType">
<xsd:sequence>
<xsd:element name="Type" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

XSD Person
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.person.org"
xmlns="http://www.person.org"
elementFormDefault="unqualified">
<xsd:complexType name="PersonType">
<xsd:sequence>
<xsd:element name="Name" type="xsd:string"/>
<xsd:element name="SSN" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>

XSD Company
<?xml version="1.0"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace=”http://www.company.org
xmlns:per="http://www.person.org"
xmlns:prod="http://www.product.org"
xmlns="http://www.company.org"
elementFormDefault="qualified">
<xsd:element name="Company">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Person"
type="per:PersonType"
maxOccurs="unbounded"/>
<xsd:element name="Product"
type="prod:ProductType"
maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>

I should be able to submit XML like the following (note:
only one element has namespace qualification -> to the
parent XSD file):

<?xml version="1.0"?>
<c:Company xmlns:c="http://www.company.org">
<Person>
<Name>John Doe</Name>
<SSN>123-45-6789</SSN>
</Person>
<Product>
<Type>Widget</Type>
</Product>
</c:Company>

My code:

namespace ConsoleApplication5
{
/// <summary>
/// Summary description for Class1.
/// </summary>
class Class1
{
/// <summary>
/// The main entry point for the
application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
ValidationEventHandler
eventHandler = new ValidationEventHandler
(Class1.ShowCompileErrors);
XmlSchemaCollection
myschemacoll = new XmlSchemaCollection();
XmlValidatingReader vr;
FileStream stream;
try
{
stream = new
FileStream(@"c:\Staging\UDG\Phase Two\Technical
Design\CompTest.xml", FileMode.Open);
//Load the
XmlValidatingReader.
vr = new
XmlValidatingReader(stream, XmlNodeType.Element, null);

//Add the schemas
to the XmlSchemaCollection object.
myschemacoll.Add
("http://www.company.org", @"c:\Staging\UDG\Phase
Two\Technical Design\company.xsd");
myschemacoll.Add
("http://www.person.org", @"c:\Staging\UDG\Phase
Two\Technical Design\person.xsd");
myschemacoll.Add
("http://www.product.org", @"c:\Staging\UDG\Phase
Two\Technical Design\product.xsd");

vr.Schemas.Add
(myschemacoll);

vr.ValidationType
= ValidationType.Schema;

vr.ValidationEventHandler += eventHandler;
while (vr.Read())

{//Console.WriteLine(" :: " + vr.Name);
}
Console.WriteLine
("Validation completed");
}
//This code
catches any XML exceptions.
catch (XmlException XmlExp)
{
Console.WriteLine
("XML ERROR: " + XmlExp.Message);
}
//This code
catches any XML schema exceptions.
catch (XmlSchemaException
XmlSchemaExp)
{
Console.WriteLine
("SCHEMA ERROR: " + XmlSchemaExp.Message);


}
//This code
catches any standard exceptions.
catch (Exception
GeneralExp)
{
Console.WriteLine
(GeneralExp.Message);
}
finally
{
//Clean up.
Console.Read();
vr = null;
myschemacoll =
null;
stream = null;
}


}

public static void
ShowCompileErrors(object sender, ValidationEventArgs args)
{
Console.WriteLine
("Validation Error: {0}", args.Message);
}
}
}

Priscilla Walmsley
7/15/2004 8:33:53 AM
Hi,

If you don't want to qualify the Person and Product elements, you should use
elementFormDefault="unqualified" in your Company schema. Currently, you
have it set to qualified, meaning that locally declared elements (namely
Person and Product) should be qualified.

Also, you need to use two xsd:import in your Company schema for the person
and product namespaces.

Hope that helps,
Priscilla

------------------------------------------------------------------
Priscilla Walmsley
Author, Definitive XML Schema / XML in Office 2003
http://www.datypic.com
------------------------------------------------------------------

[quoted text, click to view]

raj
7/15/2004 9:03:15 PM
Pricilla,

Thank you, that worked... What I'd like to do, however, is have the .net
code in charge of selecting the appropriate set of schemas instead of
hardcoding the references with an <import>. The fact that there is a
SchemaCollection implies I should be able to do this -- without having to
qualify the elements as in the Msoft example. What am I missing?

Your solution provides a viable workaround, though, so thanks :)

Cheers,

Raj

[quoted text, click to view]

Priscilla Walmsley
7/16/2004 7:16:19 AM
Hi Raj,


The main purpose of an xsd:import is just to record a dependency on another
namespace, not necessarily to import another schema document. As such, the
schemaLocation attribute on an xsd:import is optional; only the namespace
attribute is required.

So you could try specifying just the namespace in your xsd:import, and use
the code to specify the schema locations for each namespace. I haven't
tried this in .net, but I would think it would work.

Hope that helps,
Priscilla

------------------------------------------------------------------
Priscilla Walmsley
Author, Definitive XML Schema / XML in Office 2003
http://www.datypic.com
------------------------------------------------------------------

[quoted text, click to view]
raj
7/19/2004 8:05:00 AM
OK, got it.... silly me, I should have tried this from the get go. The
order the schemas are added to the schema collection is important because
the 'Add' aparently does some basic namespace resolution. So in my case,
the schemas must be added like this:

myschemacoll.Add("http://www.person.org", @"c:\Staging\person.xsd");
myschemacoll.Add("http://www.product.org", @"c:\Staging\product.xsd");

myschemacoll.Add("http://www.company.org", @"c:\Staging\company.xsd");



If I add like this:

myschemacoll.Add("http://www.company.org", @"c:\Staging\UDG\Phase
Two\Technical Design\company.xsd");

myschemacoll.Add("http://www.person.org", @"c:\Staging\UDG\Phase
Two\Technical Design\person.xsd");

myschemacoll.Add("http://www.product.org", @"c:\Staging\UDG\Phase
Two\Technical Design\product.xsd");




The first line will immediately trigger an error because the person and
product namespaces cannot be resolved to a specific location (if I don't use
the schemalocation attribute of the xsl:import).

At least that's what I _think_ is happening....

Thanks, Priscilla, for all your help...

Cheers,

Raj

PS: FWIW, this is the final Company.xsl

<?xml version="1.0"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.company.org"

xmlns:per="http://www.person.org"

xmlns:prod="http://www.product.org"

xmlns="http://www.company.org"

elementFormDefault="unqualified">


<xsd:import namespace="http://www.person.org" />

<xsd:import namespace="http://www.product.org" />


<xsd:element name="Company">

<xsd:complexType>

<xsd:sequence>

<xsd:element name="Person" type="per:PersonType"

maxOccurs="unbounded"/>

<xsd:element name="Product" type="prod:ProductType"

maxOccurs="unbounded"/>

</xsd:sequence>

</xsd:complexType>

</xsd:element>

</xsd:schema>







[quoted text, click to view]
AddThis Social Bookmark Button