# Tahir Hassan's Blog

My Technical Notes

## Wednesday, 21 January 2015

### XML Schemas: targetNamespace vs default namespace (xmlns)

Below is a typical <xs:schema> element found in an xsd file:


<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://tahirhassan.blogspot.comn"
targetNamespace="http://tahirhassan.blogspot.com"
elementFormDefault="qualified"
>
...
</xs:schema>


In the above snippet, any type defined in the document, (without a prefix, of course), will reside in the target namespace http://tahirhassan.blogspot.com. This is akin to defining a type in C# within a namespace:


namespace TahirHassanBlogspotCom
{
public class Move
{
public int Loop { get; set; }
}
}


In the above snippet, the Move type is in the namespace TahirHassanBlogspotCom. Here is the equivalent XML Schema definition file:


<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://tahirhassan.blogspot.com"
elementFormDefault="qualified"
>
<xs:complexType name="move">
<xs:attribute name="loop" type="xs:int" />
</xs:complexType>
</xs:schema>


In the above xsd, we have defined a type move in the namespace http://tahirhassan.blogspot.com, using the targetNamespace attribute. Any XML document which instantiates the move type must also "import" the namespace it is in, http://tahirhassan.blogspot.com:


<move
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tahirhassan.blogspot.com"
xsi:type="move"
loop="3" />


If an element has xmlns="some-ns" specified, then that element (and all its descending elements, unless specified otherwise) must belong in the namespace some-ns In the above example, we specify the namespace to be http://tahirhassan.blogspot.com, and the type to be move. It's a bit like instantiating our C# class defined above:


var obj = new TahirHassanBlogspotCom.Move { Loop = 3 };


If instead we want to go down the prefixing route, we associate a prefix with a namespace (e.g. thb ); we then prefix all elements in the namespace with this prefix:


<move
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:thb="http://tahirhassan.blogspot.com"
xsi:type="thb:move"
loop="3" />


There is a reason why that in most XSD schema files, the xmlns and targetNamespace are the same. It is because we are using types defined in the same document. For example, if I define a type shoe (for example):


<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:tahirhassan:shoeexample"
targetNamespace="urn:tahirhassan:shoeexample"
elementFormDefault="qualified"
>
<xs:complexType name="shoe">
<xs:attribute name="size" type="xs:int" />
</xs:complexType>
</xs:schema>


Then the type shoe is in the namespace (targetNamespace element) urn:tahirhassan:shoeexample. If we need to use this type elsewhere in the document:


<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:tahirhassan:shoeexample"
targetNamespace="urn:tahirhassan:shoeexample"
elementFormDefault="qualified"
>
<xs:complexType name="shoeCollection">
<xs:sequence minOccurs="1" maxOccurs="unbounded">
<xs:element name="shoe" type="shoe" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="shoe">
<xs:attribute name="size" type="xs:int" />
</xs:complexType>
</xs:schema>


Then if we did not include the xmlns, then the xml parser will be looking for the type shoe in the default namespace (and it will not be found). However, since we have specified that the xmlns is urn:tahirhassan:shoeexample, it will first look for shoe in urn:tahirhassan:shoeexample before looking anywhere else.

To conclude, all (non-prefixed) types defined in a document will be in the namespace declared in targetNamespace. The reason why we also include the xmlns attribute is to resolve types found in the document as being in the same namespace.

TODO: Write an article on what elementFormDefault="qualified" does.