Library tutorials & articles
Understanding XML Namespaces
- Introduction
- Why namespaces?
- Namespaces & Validation
- Unique Names
- Default Namespace
- Namespaces & Attributes
Namespaces & Validation
The role namespaces play is most obvious when you are validating an XML document against an XML Schema Definition (XSD) XSD schema. In case you are not familiar with XSD, it is an XML-based grammar used to define document structures and data types that you use in your document. You can think of XSD as a superset of Document Type Definitions (DTD). You don’t need to know much about XSD schemas for this article and I’ll explain the little bit you do need to know.
Imagine you have an XML document that contains employee information for a human resources application:
<employees>
<employee>
<id>49982</id>
<name>Bart Simpson</name>
<hireDate>2000-07-04</hireDate>
</employee>
<employee>
<id>12345</id>
<name>Hugo Simpson</name>
<hireDate>2000-05-29</hireDate>
</employee>
</employees>
You might create a schema for this document that defines a data type for the employee element like this:
<xsd:complexType name="employeeType">
<xsd:sequence>
<xsd:element name="id" type="xsd:int"/>
<xsd:element name="name" type="xsd:string"/>
<xsd:element name="hireDate" type="xsd:date"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element name="employee" type="employeeType" maxOccurs="unbounded"/>
Without going into the details of XSD, the above snippet does two things:
First, it defines a data type called employeeType that contains three elements:
id, name and hireDate. Second, it declares an element called employee of the
type employeeType. This is the XSD way of saying “the <employee> element
will contain three elements in this order: <id>, <name>, and <hireDate>”.
You can use the above schema snippet to validate the employees document and it’ll work just fine (provided you have a schema-aware validator like XML Spy V3.5). Now, imagine the payroll application wants to share this employee information and add some more to it. For example, the payroll application wants to keep track of employee salary and the taxes being deducted (this is way oversimplified, but who wants to learn the 2001 payroll taxes laws?):
<employees>
<employee>
<id>49982</id>
<name>Bart Simpson</name>
<hireDate>2000-07-04</hireDate>
<salary>4000765.00</salary>
<taxes>3980765.27</taxes>
</employee>
<employee>
<id>12345</id>
<name>Hugo Simpson</name>
<hireDate>2000-05-29</hireDate>
<salary>82000.00</salary>
<taxes>16567.87</taxes>
</employee>
</employees>
How should you handle this? Do you update the HR schema to reflect the new <salary> and <taxes> elements?
That might seem like a good choice at first, but it results in two separate
applications sharing the same schema document, which is likely to result in
ownership and maintenance problems. It would be much better if you can separate
the data types that belong to HR from the data types that belong to payroll
and allow each application’s team to have control over there data types with
no potential of messing up each other’s schemas.
You can do that by simply
placing those data types in different buckets when you define them. Those buckets
are called namespaces. Lets say you define a bucket or namespace called HRData
and another one called payrollData. You can then make the payroll application
team in charge of maintaining data types in the payrollData namespace and the
HR application team in charge of maintaining types in the HRData namespace.
You will need a way to indicate that the <salary> and <taxes> elements
belong to the payrollData namespace while all other elements belong to the
HRData namespace. To do this you prefix each element name with the namespace
and a colon like this:
<HRData:employees>
<HRData:employee>
<HRData:id>49982</HRData:id>
<HRData:name>Bart Simpson</HRData:name>
<HRData:hireDate>2000-07-04</HRData:hireDate>
<payrollData:salary>4000765.00</payrollData:salary>
<payrollData:taxes>3980765.27</payrollData:taxes>
</HRData:employee>
<HRData:employee>
<HRData:id>12345</HRData:id>
<HRData:name>Hugo Simpson</HRData:name>
<HRData:hireDate>2000-05-29</HRData:hireDate>
<payrollData:salary>82000.00</payrollData:salary>
<payrollData:taxes>16567.87</payrollData:taxes>
</HRData:employee>
</HRData:employees>
Don’t be fooled by the apparent complexity of this snippet. All I did is add the HRData and payrollData prefixes before each element name. I don’t know about you, but I’d rather keep the namespace prefixes as short as possible. To do this, you come up with a short prefix, possibly as short as one letter, and map that prefix to the real namespace name. For example, you might decide to use py for payrollData and hr for HRData:
<hr:employees xmlns:hr="HRData" xmlns:py="payrollData">
<hr:employee>
<hr:id>49982</hr:id>
<hr:name>Bart Simpson</hr:name>
<hr:hireDate>2000-07-04</hr:hireDate>
<py:salary>4000765.00</py:salary>
<py:taxes>3980765.27</py:taxes>
</hr:employee>
<hr:employee>
<hr:id>12345</hr:id>
<hr:name>Hugo Simpson</hr:name>
<hr:hireDate>2000-05-29</hr:hireDate>
<py:salary>82000.00</py:salary>
<py:taxes>16567.87</py:taxes>
</hr:employee>
</hr:employees>
The syntax for defining a namespace-prefix mapping is: xmlns:prefix=”namespace” where
prefix is the short prefix you’ll use in the document and namespace is the
actual namespace name that the prefix refers to. Once you’ve defined the prefix,
you can use it in your document instead of writing out the entire namespace
name in front of each element name. When using namespaces, element and attribute
names have two parts: the prefix e.g. hr or py and the local name e.g. employee
or salary. The two parts together form the qualified name or QName, e.g. hr:employee
or py:salary.
Now you can easily create two different schemas, one that defines the HR types in the HRData namespace, and one that defines the payroll types in the payrollData namespace. The syntax you use to do this is part of XSD and is beyond the scope of this article.
Related articles
Related discussion
-
vb6 generated help file not working in Window 7 and Vista
by Thushan Fernando (1 replies)
-
doctype in xml using c#.net
by madarapurajesh (0 replies)
-
Like statement in Xpath
by madarapurajesh (3 replies)
-
Problem looping through xml file to play a flv video file
by Bozmeister (0 replies)
-
Creating a Windows Service in VB.NET
by davidvanr (108 replies)
Related podcasts
-
LINQ to XML
Scott's been poking around with LINQ to XML and reports his findings to Carl about life with XDocuments and XElements. They also talk about the bridge classes that link (no pun intended) System.Xml and System.Xml.Linq.
Hi,
I'm having a problem with xml namespaces.
My application accepts an xml document from another application, which is then validated using an xsd. The xsd has a namespace defined and uses a prefix "ns1" for the tags. The application from which i am supposed to get my xml doc for processing keeps changing the prefix but the namespace URI is the same. This causes the xsd to throw an error.
Is there any way by which the xsd can accept any prefix from the same URI?
Glad you found the answer.
The beloe format gives the required o/p
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sl="com.klm.cargo.ebiza.freightWebService">
<xslutput indent="no" method="html"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/SERVICE">
<sl:getAvailabilityResponse>
<slutFVA>
<sl:msgEnvelope >
<slriority>high</slriority>
<sl:recipientId>1 -2n</sl:recipientId>
<sl:gmt>W3</sl:gmt>
<sl:senderInfo>WQere</sl:senderInfo>
</sl:msgEnvelope>
<sl:standardMessageIdentification> GTY</sl:standardMessageIdentification>
<sl:version>2n</sl:version>
<xsl:for-each select="AVLBLTY/FLIGHTLIST/STRETCH ">
<sl:scheduleInformationAnswer>
<sl:scheduleAndAvailabiltyinformationDetails>
<sl:date>
<slay>
<xsl:call-template name="DATEFORMAT1_TEMPLATE"/>
</slay>
</sl:date></sl:scheduleInformationAnswer></xsl:for-each>
</slutFVA>
</sl:getAvailabilityResponse>
</xsl:template>
<xsl:template name="DATEFORMAT1_TEMPLATE">
<!--day-->
<xsl:variable name="date" select="@DEPDATE"/>
<xsl:value-of select="substring($date,7,2)"/>
</xsl:template>
The beloe format gives the required o/p
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sl="com.klm.cargo.ebiza.freightWebService">
<xsl
<xsl:strip-space elements="*"/>
<xsl:template match="/SERVICE">
<sl:getAvailabilityResponse>
<sl
<sl:msgEnvelope >
<sl
<sl:recipientId>1 -2n</sl:recipientId>
<sl:gmt>W3</sl:gmt>
<sl:senderInfo>WQere</sl:senderInfo>
</sl:msgEnvelope>
<sl:standardMessageIdentification> GTY</sl:standardMessageIdentification>
<sl:version>2n</sl:version>
<xsl:for-each select="AVLBLTY/FLIGHTLIST/STRETCH ">
<sl:scheduleInformationAnswer>
<sl:scheduleAndAvailabiltyinformationDetails>
<sl:date>
<sl
<xsl:call-template name="DATEFORMAT1_TEMPLATE"/>
</sl
</sl:date></sl:scheduleInformationAnswer></xsl:for-each>
</sl
</sl:getAvailabilityResponse>
</xsl:template>
<xsl:template name="DATEFORMAT1_TEMPLATE">
<!--day-->
<xsl:variable name="date" select="@DEPDATE"/>
<xsl:value-of select="substring($date,7,2)"/>
</xsl:template>
Hi lurs thanks for the reply....
Here i have one more query
i have a input XML beloe which does not have any namespace which is given as a input to a XSL and i need a XML which shuld have a XML with the namespace
INPUT
<AVLBLTY>
<FLIGHTLIST DEPDATE="20041104">
<STRETCH BRD="AMS" PALLETIZED="N" STOPS="0" CAO="N" AIRCRAFTTYPE="739">
</STRETCH>
<AVLBLTY>
XSL
is the beloe XSL is a correct format ????
<xsl:transform version="1.0" xmlns:kl="http://www.w3.org/1999/XSL/Transform" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="no" method="html"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/SERVICE">
<kl:getAvailabilityResponse>
<kl:outFVA>
<kl:msgEnvelope >
<kl:providerId> 1-2n</kl:providerId>
<kl:priority>high</kl:priority>
<kl:recipientId>1 -2n</kl:recipientId>
<kl:gmt>W3</kl:gmt>
<kl:senderInfo>WQere</kl:senderInfo>
</kl:msgEnvelope>
<kl:standardMessageIdentification> GTY</kl:standardMessageIdentification>
<kl:version>2n</kl:version>
<xsl:for-each select="AVLBLTY/FLIGHTLIST/STRETCH ">
<kl:scheduleInformationAnswer>
<kl:scheduleAndAvailabiltyinformationDetails>
<kl:date>
<kl:Day>
<xsl:call-template name="DATEFORMAT1_TEMPLATE"/>
</kl:Day>
</kl:date>
</kl:scheduleAndAvailabiltyinformationDetails>
</kl:scheduleInformationAnswer>
</xsl:for-each>
</kl:outFVA></kl:getAvailabilityResponse> </xsl:template>
<xsl:template name="DATEFORMAT1_TEMPLATE">
<!--day-->
<xsl:Value-of select="@DEPDATE"/>
</xsl:template>
i need the o/p XML in the following format
<kl:getAvailabilityResponse> // here the o/p sholud have name space for the o/p XML tags
//some more
</kl:getAvailabilityResponse>
However your stylesheet also needs to declare the namespace.
So your xsl:transform (or xsl:stylesheet) element needs to look like this:
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmnls:cargoInterfaceMessage="http://www.klm.cargo.com">
...
Otherwise, XSLT will complain that it doesn't recognize the 'cargoInterfaceMessage' prefix.
Lars
www.huttar.net
some thing like
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xslutput indent="no" method="html"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/cargoInterfaceMessage:FVR"> //is it a correct way to match a namespace
</xsl:template>
</xsl:transform>
For the Above XSL i hav a XML input as
<cargoInterfaceMessage:FVR xmnls:cargoInterfaceMessage ="http://www.klm.cargo.com" >
<cargoInterfaceMessage:msgEnvelope>
<cargoInterfaceMessageroviderid> 1-2n</cargoInterfaceMessageroviderid>
<cargoInterfaceMessageriority> high</cargoInterfaceMessageriority>
<cargoInterfaceMessage:recipientid>1-2yt</cargoInterfaceMessage:recipientid>
<cargoInterfaceMessage:gmt>w3</cargoInterfaceMessage:gmt>
<cargoInterfaceMessage:senderinfo>wqare</cargoInterfaceMessage:senderinfo>
<cargoInterfaceMessage:senderid>1-2n</cargoInterfaceMessage:senderid>
</cargoInterfaceMessage:msgEnvelope>
is it the correct way ????
some thing like
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xslutput indent="no" method="html"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/cargoInterfaceMessage:FVR"> //is it a correct way to match a namespace
</xsl:template>
</xsl:transform>
For the Above XSL i hav a XML input as
<cargoInterfaceMessage:FVR xmnls:cargoInterfaceMessage ="http://www.klm.cargo.com" >
<cargoInterfaceMessage:msgEnvelope>
<cargoInterfaceMessageroviderid> 1-2n</cargoInterfaceMessageroviderid>
<cargoInterfaceMessageriority> high</cargoInterfaceMessageriority>
<cargoInterfaceMessage:recipientid>1-2yt</cargoInterfaceMessage:recipientid>
<cargoInterfaceMessage:gmt>w3</cargoInterfaceMessage:gmt>
<cargoInterfaceMessage:senderinfo>wqare</cargoInterfaceMessage:senderinfo>
<cargoInterfaceMessage:senderid>1-2n</cargoInterfaceMessage:senderid>
</cargoInterfaceMessage:msgEnvelope>
is it the correct way ????
some thing like
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl
<xsl:strip-space elements="*"/>
<xsl:template match="/cargoInterfaceMessage:FVR"> //is it a correct way to match a namespace
</xsl:template>
</xsl:transform>
For the Above XSL i hav a XML input as
<cargoInterfaceMessage:FVR xmnls:cargoInterfaceMessage ="http://www.klm.cargo.com" >
<cargoInterfaceMessage:msgEnvelope>
<cargoInterfaceMessage
<cargoInterfaceMessage
<cargoInterfaceMessage:recipientid>1-2yt</cargoInterfaceMessage:recipientid>
<cargoInterfaceMessage:gmt>w3</cargoInterfaceMessage:gmt>
<cargoInterfaceMessage:senderinfo>wqare</cargoInterfaceMessage:senderinfo>
<cargoInterfaceMessage:senderid>1-2n</cargoInterfaceMessage:senderid>
</cargoInterfaceMessage:msgEnvelope>
is it the correct way ????
Just want to say thanks for this article. I'm new to XML and this helped clear my namespace confusion immediately. Much better than every other article that I have read so far... :-)
I can't believe something so simple confused the heck outta me...
Thanks.
Craig.
I didn't see what this article said about it, but it's true that default namespaces do not apply directly to attributes.
OK, I looked at what the article said, and I believe he is mistaken. (You notice his example didn't include any attributes.)
An interesting article! Does anybody now how to apply using these namespaces in XPath? For example selecting a node or nodes from a specific namespace.
For example in an XSL stylesheet, you would put the namespace declaration in the stylesheet (e.g. on the xsl:stylesheet element), and then use the prefix directly in the XPath expression as part of a nametest. E.g.
<xsl:stylesheet xmlns:foo="http://barbaz" ...>
... select="/foo:schedule/@*" ...
Note that the default namespace DOES NOT apply to unprefixed elements (or attributes) in XPath expressions.
Not in XPath 1.0 anyway; there is a way to do that in 2.0 though.
Lars
I didn't see what this article said about it, but it's true that default namespaces do not apply directly to attributes.
Based on the http://www.w3.org/TR/REC-xml-names/, default namespace do not apply directly to attributes. But in this article it says you can define a default namespace that applies to all non-prefixed elements and attributes. So which one is right?
An interesting article! Does anybody now how to apply using these namespaces in XPath? For example selecting a node or nodes from a specific namespace.
This thread is for discussions of Understanding XML Namespaces.