What does targetNamespace do ? Am I getting it right?

此生再无相见时 提交于 2019-12-22 10:44:14

问题


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:

  • This schema itself belongs to http://www.w3.org/2001/XMLSchema namespace
  • The root of the XML instance should belong to http://www.cmu.edu/ns/blank namespace
  • 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
  • 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 type studentType and a global element student of this type, and declares the people 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 extends p: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 the people schema.


    来源:https://stackoverflow.com/questions/16481870/what-does-targetnamespace-do-am-i-getting-it-right

    标签
    易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
    该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!