Unlike a Document Type Definition (DTD), XML Schemas are extensible. That is, they are built on an open content model. Schema authors are free to add their own elements and attributes to XML Schema documents. For example, you could add additional constraints to a declaration for a "pages" element. The following sample code declares the "pages" element and assigns it an "int" datatype. Extended tags from the "myExt" namespace are used to augment this information with an added limitation that books must have a minimum of 50 pages and a maximum of 100 pages.
<ElementType name="pages" xmlns:myExt="urn:myschema-extensions"> <datatype dt:type="int" /> <myExt:min>50</myExt:min> <myExt:max>100</myExt:max> </ElementType>
While validation will only check that the value of a particular "pages" element is an integer, your application can use the information provided by the added elements in the "myExt" namespace to perform additional validation.
It's worth noting that the elements that Microsoft added to the schema were qualified by a namespace. Use of a namespace is a requirement for adding elements and attributes to a schema. For more information on namespaces, see Introduction to Namespaces.
Custom schemas can be built out of standard parts. For example, suppose that a definition for an "Address" element from another schema has met your needs. With Namespaces, this schema can be used directly with a reference to the original schema rather than copying the definition.
To reference an element defined in another schema, you must first use a namespace declaration to introduce the other schema. This declaration consists of an attribute beginning with "xmlns:", followed by a name of your choice called the "prefix," and lastly with a value that is the Universal Resource Identifier (URI) of the other schema.
<ElementType name="PurchaseOrder" xmlns:abcde="http://electrocommerce.org/stuff.xml">
The schema has a URI of "http://electrocommerce.org/stuff.xml" and a prefix of "abcde." The URI identifies the other schema precisely; the prefix is a local name that you now use to refer to that schema and to the elements it defines as though they were defined in your schema. If the other schema has a suitable "shipTo" element defined, you can use it by writing,
<ElementType name="shipTo" xmlns:abcde="http://electrocommerce.org/stuff.xml"> <element type="abcde:Address"/> </ElementType>
In the type attribute of the first sub-element declaration for the value "abcde:Address," the prefix "abcde" is matched to the enclosing namespace declaration, and thus "abcde:Address" has the effect of meaning "the Address element" as defined in the schema "http://electrocommerce.org/stuff.xml."
However, this has an effect on the XML document as well. For example, in the following purchase order document you also need to reference the other schema namespace.
<PurchaseOrder xmlns:abcde="http://electrocommerce.org/stuff.xml"> <shipTo> <abcde:Address> <abcde:name>Alice Smith</abcde:name> <abcde:street>123 Maple Street</abcde:street> <abcde:city>Mill Valley</abcde:city> <abcde:state>CA</abcde:state> <abcde:zip>90952</abcde:zip> </abcde:Address> </shipTo> <orderDate>1999-05-20</orderDate> <shipDate>1999-05-25</shipDate> <comments> Get these things to me in a hurry, my lawn is going wild! </comments> <Items> <Item> <productName>Lawnmower, model BUZZ-1</productName> <quantity>1</quantity> <price>148.95</price> </Item> <Item> <productName>Weed Wacker, model SNOOZE-2</productName> <quantity>1</quantity> <price>39.98</price> </Item> </Items> </PurchaseOrder>
You can determine that the "Address" element is defined by the schema at "http://electrocommerce.org/stuff.xml." When you build specialized schemas from more widely-understood standard parts, like the "Address" element above, those portions can often be processed by standard software components. For example, if you have an XSL style sheet template available for the "Address" element, as defined in the schema "http://electrocommerce.org/stuff.xml," you can reuse this general-purpose address styling code anywhere that "Address" appears.
The same prefix is used in both the schema and in the document instance: in the schema for all purchase orders, and in a specific purchase order. But this isn't necessary, since the prefix is only a local alias for the namespace URI, and you can use any prefix you like in the document instance. You are only required to use the same prefix in a document both when you declare the namespace and when you use elements from that namespace. For example,
<PurchaseOrder xmlns:z="http://electrocommerce.org/stuff.xml"> <shipTo> <z:Address> <z:name>Alice Smith</z:name> <z:street>123 Maple Street</z:street> <z:city>Mill Valley</z:city> <z:state>CA</z:state> <z:zip>90952</z:zip> </z:Address> </shipTo> </PurchaseOrder>
The declaration of a namespace is scoped to the element on which it appears. It makes the namespace prefix available, and associates it with the URI for that element and anything it contains, unless overridden by another, enclosed namespace declaration. Therefore, since the namespace is only used on the "Address" element, the namespace declaration could appear on the "Address" element instead, as follows,
<PurchaseOrder> <shipTo> <z:Address xmlns:z="http://electrocommerce.org/stuff.xml"> <z:name>Alice Smith</z:name> <z:street>123 Maple Street</z:street> <z:city>Mill Valley</z:city> <z:state>CA</z:state> <z:zip>90952</z:zip> </z:Address> </shipTo> </PurchaseOrder>
You can also omit a prefix to a namespace, which can make for more legible documents. In the following example, by omitting the prefix from the namespace declaration, you indicate that any sub-element without a prefix is defined by the specified namespace.
<PurchaseOrder> <shipTo> <Address xmlns="http://electrocommerce.org/stuff.xml"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </Address> </shipTo> </PurchaseOrder>
Namespace prefixes are only for intra-document bookeeping. What matters is the corresponding URI, so all four of the previous examples' "Address" elements mean exactly the same thing.
Although the "Address" element has been identified as being defined by the schema "http://electrocommerce.org/stuff.xml," "PurchaseOrder" has not been similarly tied to a schema. To do this, assuming a schema named "http://fabrikam.com/PO.xml" defines a "PurchaseOrder," you can write:
<PurchaseOrder xmlns="http://fabrikam.com/PO.xml"> <shipTo> <Address xmlns="http://electrocommerce.org/stuff.xml" > <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </Address> </shipTo> <orderDate>1999-05-20</orderDate> <shipDate>1999-05-25</shipDate> <comments> Get these things to me in a hurry, my lawn is going wild! </comments> <Items> <Item> <productName>Lawnmower, model BUZZ-1</productName> <quantity>1</quantity> <price>148.95</price> </Item> <Item> <productName>Baby Monitor, model SNOOZE-2</productName> <quantity>1</quantity> <price>39.98</price> </Item> </Items> </PurchaseOrder>
This declares that the "PurchaseOrder" element, and all elements it contains, are defined within the schema "http://fabrikam.com/PO.xml" except for "Address" and the elements it contains, which are defined within xmlns="http://electrocommerce.org/stuff.xml." In both cases, explicit prefixes are omitted.
You can declare multiple namespaces on a single element. You can also use several prefixes to refer to the same namespace. The following example shows this, merely to demonstrate that it can be done, and to make the point that this document is functionally equivalent to the previous one.
<PurchaseOrder xmlns:a="http://fabrikam.com/PO.xml" xmlns:b="http://electrocommerce.org/stuff.xml" xmlns:c="http://electrocommerce.org/stuff.xml"> <a:shipTo> <b:Address > <c:name>Alice Smith</c:name> <b:street>123 Maple Street</b:street> <c:city>Mill Valley</c:city> <b:state>CA</b:state> <c:zip>90952</c:zip> </b:Address> </a:shipTo> <a:orderDate>1999-05-20</a:orderDate> <a:shipDate>1999-05-25</a:shipDate> <a:comments> Get these things to me in a hurry, my lawn is going wild! </a:comments> <a:Items> <a:Item> <a:productName>Lawnmower, model BUZZ-1</a:productName> <a:quantity>1</a:quantity> <a:price>148.95</a:price> </a:Item> <a:Item> <a:productName>Baby Monitor</a:productName> <a:quantity>1</a:quantity> <a:price>39.98</a:price> </a:Item> </a:Items> </a:PurchaseOrder>
If a document schema has elements with an open content model, you can include elements not mentioned in the original schema, provided they are assigned to a specific namespace, either with a default namespace in scope or with a prefix. You can also include undefined attributes in an element, provided the attribute is qualified by a prefix and the prefix is in scope. For example, suppose that a third schema defines an element called "trackingInformation." Since "PurchaseOrder" is defined as having an open content model, you can simply add this element directly to the instance:
<PurchaseOrder xmlns="http://fabrikam.com/PO.xml"> <shipTo> <Address xmlns="http://electrocommerce.org/stuff.xml"> <name>Alice Smith</name> <street>123 Maple Street</street> <city>Mill Valley</city> <state>CA</state> <zip>90952</zip> </Address> </shipTo> <orderDate>1999-05-20</orderDate> <shipDate>1999-05-25</shipDate> <comments> Get these things to me in a hurry, my lawn is going wild! </comments> <Items> <Item> <productName>Lawnmower, model BUZZ-1</productName> <quantity>1</quantity> <price>148.95</price> </Item> <Item> <productName>Baby Monitor, model SNOOZE-2</productName> <quantity>1</quantity> <price>39.98</price> </Item> </Items> <trackingInformation xmlns="http://somewhere.com/tracking.xml"> <route>1234-5678</route> <signature>32143912850-3959159=1395</signature> </trackingInformation> </PurchaseOrder>
Because namespace qualification is required for any undefined attribute or element, the "trackingInformation" element would not have been valid if its "xmlns" attribute had been omitted.