Handling Namespaces


Mostly what we've talked about in this chapter is how to perform some common transformation tasks . This section still deals with a situation you are very likely to encounter, but it deals strictly with XSLT care and feeding. We're talking about namespaces. Namespaces can be tricky any time you work with them, and XSLT is no exception. Fortunately, we can do a few things to keep ourselves out of too much trouble.

There are several key points to remember about namespaces. Your stylesheet, first and foremost, is still an XML document. To be well formed it must obey all the usual rules concerning namespace handling. The upshot to this is that namespace declarations need to be made at the appropriate scope within the document. This is usually in the root xsl:stylesheet Element, but it doesn't have to be. If you don't declare your namespaces in the root Element, just make sure you put them where their scope is appropriate.

Another thing to remember is that if your source document uses namespace prefixes on some of your Elements, you had better include that prefix in your match expressions. (There are some other ways to reference namespaces in XPath expressions, but the simplest way is just to use the prefix used in the source document.)

The most common namespace problems that most of us will encounter have to do with converting between documents that use named namespaces and those that don't. Let's take a simple example of converting from our own invoice document, which doesn't use named namespaces, to a standard invoice that references a named namespace. The standard invoice also has a schema reference. Here's our source document.

Source (NamespacesAdd.xml)
 <?xml version="1.0" encoding="UTF-8"?> <MyInvoice>   <InvoiceNum>QA-Z33WX</InvoiceNum>   <DueDate>2003-02-15</DueDate> </MyInvoice> 

We need to create the following result document.

Result (NamespacesAdded.xml)
 <?xml version="1.0" encoding="UTF-8"?> <std:Invoice     xsi:schemaLocation="urn:org.standardsrus.names     http://www.standardsrus.schemas/V0756/invoice.xsd"     xmlns:std="urn:org.standardsrus.names"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">   <InvoiceNumber>QA-Z33WX</InvoiceNumber>   <InvoiceDueDate>2003-02-15</InvoiceDueDate> </std:Invoice> 

Here is the stylesheet for the transformation.

Stylesheet (NamespacesAdd.xsl)
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:std="urn:org.standardsrus.names"     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >   <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>   <xsl:template match="MyInvoice">     <std:Invoice xsi:schemaLocation="urn:org.standardsrus.names         http://www.standardsrus.schemas/V0756/invoice.xsd">       <InvoiceNumber>         <xsl:value-of select="InvoiceNum"/>       </InvoiceNumber>       <InvoiceDueDate>         <xsl:value-of select="DueDate"/>       </InvoiceDueDate>     </std:Invoice>   </xsl:template> </xsl:stylesheet> 

Going this way isn't too bad. The main things to note are that we declare all our namespaces in the stylesheet's root Element and that in the literal result root Element we add the xsi:schemaLocation Attribute. When the source is processed with the stylesheet, all the namespace declarations in the stylesheet root (except for the XSLT namespace) are copied into the root Element of the result document.

Going back the other way, from a source that uses named namespaces to a result that doesn't, can be tricky. Let's begin with the NamespacesAdded.xml document as the source and process it using the following stylesheet.

Stylesheet (NamespacesNotRemoved.xsl)
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:std="urn:org.standardsrus.names">   <xsl:output method="xml" version="1.0" encoding="UTF-8"       indent="yes"/>   <xsl:template match="std:Invoice">     <MyInvoice>       <InvoiceNum>         <xsl:value-of select="InvoiceNumber"/>       </InvoiceNum>       <DueDate>         <xsl:value-of select="InvoiceDueDate"/>       </DueDate>     </MyInvoice>   </xsl:template> </xsl:stylesheet> 

Note that we have to include the std: namespace prefix on the root Element in the match Attribute. By using the stylesheet above we get the following undesired result document.

Result (NamespacesNotRemoved.xml)
 <?xml version="1.0" encoding="UTF-8"?> <MyInvoice xmlns:std="urn:org.standardsrus.names">   <InvoiceNum>QA-Z33WX</InvoiceNum>   <DueDate>2003-02-15</DueDate> </MyInvoice> 

So, how do we get rid of the namespace reference on the root Element of our result document? We use a special Attribute on the stylesheet root Element, exclude-result-prefixes . For this Attribute's value we put a whitespace-separated list of the prefixes of all the namespace declarations that we don't want copied into the result document's root Element.

Stylesheet (NamespacesRemoved.xsl)
 <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0"     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"     xmlns:std="urn:org.standardsrus.names"     exclude-result-prefixes="std">   <xsl:output method="xml" version="1.0" encoding="UTF-8"     indent="yes"/>   <xsl:template match="std:Invoice">     <MyInvoice>       <InvoiceNum>         <xsl:value-of select="InvoiceNumber"/>       </InvoiceNum>       <DueDate>         <xsl:value-of select="InvoiceDueDate"/>       </DueDate>     </MyInvoice>   </xsl:template> </xsl:stylesheet> 
Result (NamespacesRemoved.xml)
 <?xml version="1.0" encoding="UTF-8"?> <MyInvoice>   <InvoiceNum>QA-Z33WX</InvoiceNum>   <DueDate>2003-02-15</DueDate> </MyInvoice> 

Everything is the same in the stylesheet except for the addition of this one Attribute.

I'm sure that if you work with XSLT long enough you will get bitten by other types of namespace problems. Keep the basics in mind, have your references ready, and I'm sure you'll persevere.



Using XML with Legacy Business Applications
Using XML with Legacy Business Applications
ISBN: 0321154940
EAN: 2147483647
Year: 2003
Pages: 181

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net