问题
Here is the <schema>
tag of my XSD:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://www.cmu.edu/ns/blank"
targetNamespace="http://www.cmu.edu/ns/blank"
elementFormDefault="qualified">
If my understanding is correct, here is what it means:
http://www.w3.org/2001/XMLSchema
namespace http://www.cmu.edu/ns/blank
namespace http://www.cmu.edu/ns/blank
namespace as elementFormDefault
is qualified Question1: Is my understanding correct. If not, what is wrong ?
Question2 Look at the undermentioned XML instance:
<people
xmlns="http://www.cmu.edu/ns/blank"
xmlns:xsi="http://www.w3c.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.cmu.edu/ns/blank student.xsd"
>
<student>
<name>John</name>
<course>Computer Technology</course>
<semester>6</semester>
<scheme>E</scheme>
</student>
</people>
Here everything belongs to http://www.cmu.edu/ns/blank
namespace including <student>
and the elements contained within because of elementFormDefault
. Correct?
Question3
Now, I want to add <student>
from various Universities. with prefixes like berk
for Berkley, harv
for Harvard, etc. Each <student>
has a different set of elements within. And I want to validate that. How is that possible?
回答1:
(1) The first two points are OK; the third one:
All the elements within the XML instance which do not have a prefix automatically belong to http://www.cmu.edu/ns/blank namespace as elementFormDefault is qualified
is incorrect.
Declaring a prefix in the schema doesn't mean that the XML instance must use the same prefixes. Any namespace declaration in the XSD file, applies only to the XML file that is XSD (XSD is an XML, therefore...)
In general, there is no way to assume anything about any prefixed or un-prefixed element name; i.e. below examples are all correct.
<some xmlns="" .../>
<some xmlns="urn:tempuri-org:XSD:1" .../>
<x:some xmlns:x="urn:tempuri-org:XSD:1" .../>
The only sure thing is that the only way to represent an unqualified name is through a name without a prefix (i.e. one cannot prefix the "empty" namespace).
elementFormDefault
controls the form of the element's name, when an element is declared within a content model (i.e. is not global).
(2) Partially correct. The part because of elementFormDefault.
is incorrect. Again, XSD is just one schema spec; XML exists and has its own rules, irrespective of XSD, or any other schema language. The rule that applies here is that of XML namespaces, specifically scoping.
(3) You would have to create an XSD for each namespace; within each namespace, you declare the student and it's content. Then the XSD which defines people would import the other XSDs and reference students appropriately.
So this is a basic setup:
Berkeley.xsd
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="urn:berkeley-org" xmlns="urn:berkeley-org" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="student"/>
</xsd:schema>
Harvard.xsd
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="urn:harvard-org" xmlns="urn:harvard-org" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="student"/>
</xsd:schema>
people.xsd
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="urn:people-org" xmlns="urn:people-org" xmlns:harv="urn:harvard-org" xmlns:berk="urn:berkeley-org" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="urn:harvard-org" schemaLocation="harvard.xsd"/>
<xsd:import namespace="urn:berkeley-org" schemaLocation="berkeley.xsd"/>
<xsd:element name="people">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element ref="harv:student"/>
<xsd:element ref="berk:student"/>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
The files graph:

A sample XML (shows the use of namespaces):
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- Sample XML generated by QTAssistant (http://www.paschidev.com) -->
<people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:harv="urn:harvard-org" xmlns:berk="urn:berkeley-org" xmlns="urn:people-org">
<harv:student/>
<berk:student/>
</people>

回答2:
Petru's answer is a good one, but it requires that the base "people" schema be aware of (and import) all the different college-specific schemas - if you want to add a new college you have to update the base schema to match. A different approach would be to reverse the direction of the imports by having the base schema declare a base "student" type, possibly with elements that are common to all colleges, which the other schemas extend using the substitution group mechanism.
people.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:people"
xmlns:p="urn:people"
elementFormDefault="unqualified">
<xs:element name="people">
<xs:complexType>
<xs:sequence>
<xs:element ref="p:student" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="studentType">
<xs:sequence>
<xs:element name="name" type="xs:string" />
</xs:sequence>
</xs:complexType>
<xs:element name="student" type="p:studentType" />
</xs:schema>
harvard.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:harvard"
xmlns:p="urn:people"
elementFormDefault="unqualified">
<xs:import namespace="urn:people" schemaLocation="people.xsd"/>
<xs:element name="student" substitutionGroup="p:student">
<xs:complexType>
<xs:extension base="p:studentType">
<xs:element name="harvardId" type="xs:string" />
</xs:extension>
</xs:complexType>
</xs:element>
</xs:schema>
berkeley.xsd
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="urn:berkeley"
xmlns:p="urn:people"
elementFormDefault="unqualified">
<xs:import namespace="urn:people" schemaLocation="people.xsd"/>
<xs:element name="student" substitutionGroup="p:student">
<xs:complexType>
<xs:extension base="p:studentType">
<xs:element name="berkeleyId" type="xs:string" />
</xs:extension>
</xs:complexType>
</xs:element>
</xs:schema>
Instance document
<p:people xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:harv="urn:harvard" xmlns:berk="urn:berkeley" xmlns:p="urn:people"
xsi:schemaLocation="urn:people people.xsd urn:harvard harvard.xsd
urn:berkeley berkely.xsd>
<harv:student>
<name>John</name>
<harvardId>12345</harvardId>
</harv:student>
<berk:student>
<name>Mary</name>
<berkeleyId>ABCDE</berkeleyId>
</berk:student>
</p:people>
Note that I've used elementFormDefault="unqualified"
in this example to simplify the namespaces in the instance documents. If I'd used qualified
then you'd have to say something like
<harv:student>
<p:name>John</p:name>
<harv:harvardId>12345</harv:harvardId>
</harv:student>
(i.e. the elements under harv:student
that were inherited from the base p:studentType
would have to be in the urn:people
namespace but those declared in the harvard.xsd
extension would have to be in the urn:harvard
namespace).
The key points to understand here are:
- the
people
schema declares a global complex typestudentType
and a global elementstudent
of this type, and declares thepeople
element as a sequence of{urn:people}student
. - each college-specific schema declares its own element with
substitutionGroup="p:student"
and with a type that extendsp:studentType
. This tells the validator that anywhere where a{urn:people}student
is expected, a{urn:college}student
is also acceptable. - when you want to add a new college, you just create a similar schema with a new element in the same
substitutionGroup
and you can refer to that in instance documents - there's no need to change thepeople
schema.
来源:https://stackoverflow.com/questions/16481870/what-does-targetnamespace-do-am-i-getting-it-right