Namespaces are a mechanism by which similar tags from different DTDs can be used in the same XML document. For example, let's say you create an XML document listing the description of a car, and suppose you have two stereo brands and their price. The XML document will look like this: <?xml version='1.0'?> <car> <color>red</color> <stereo> <brandname>xxxxxx</brandname> <price>200</price> </stereo> <stereo> <brandname>yyy</brandname> <price>1200</price> </stereo> </car> Now assume that the price has two different definitions on how it should be processed. This can occur if the stereo vendors are different. In such a case, although the element name is the same, the two price elements belong to different definitions. To allow such cases, in which the XML data is referring to multiple DTDs, the namespace feature is used. NOTE By default, if no namespaces are defined, all the elements and attributes belong to a single default namespace. A namespace essentially maps an element prefix to a URI, which uniquely resolves the tag to a specific DTD. This is how the price element problem could be solved: Assume that the DTD for describing the stereo is detailed in www.carstereo.com/DTD/carstereo.dtd. So, with namespaces, the XML document will look like this: <?xml version='1.0'?> <car> <color>red</color> <stereo> <brandname>xxxxxx</brandname> <vendor1:price>200</vendor1:price> </stereo> <stereo> <brandname>yyy</brandname> <vendor2:price>1200</vendor1:price> </stereo> </car> With the namespaces enabled, the ambiguity caused by similar tags in an XML document is resolved. To understand how the SAX APIs handle namespaces, you will now modify the CarParts.xml file and the MyXMLhandler application. For the sake of brevity and clarity of code and output, use the CarParts.xml file and MyXMLHandler.java application located in the example03 folder as the source and modify them. First, you will modify the CarParts.xml file and introduce namespaces. To do so, add the lines listed in bold in Listing 4.10. Listing 4.10 Introducing Namespaces into CarParts.xml<?xml version='1.0'?> <carparts> <engines> <engine xmlns="http://enginesonline.com" xmlns:registration="http://enginesregistration.com" xmlns:enginespecs="http://enginespecs.com"> <mpfiengine enginespecs:documentation='ALFA37D'> <registration:number>ALFA37D </registration:number> </mpfiengine> </engine> <engine> <mviengine> </mviengine> </engine> </engines> <carbody> </carbody> <wheel> </wheel> <carstereo> </carstereo> </carparts> Next, modify the MyXMLHandler.java application to handle the namespaces. For an application to handle namespaces, the parser needs to be set as namespace aware. This is done by the setNamespaceAware() method of the SAXParserFactory class. To make a parser namespace aware, add the line listed in bold in Listing 4.11. Listing 4.11 Making MyXMLHandler Namespace Awarestatic public void main(String[] args) throws Exception { System.out.println("\nVersion 0404.0 of MyXMLHandler in example0404\n"); /*Create a SAX Parser Factory*/ SAXParserFactory parserFactory = SAXParserFactory.newInstance(); /*enable namespacing*/ parserFactory.setNamespaceAware(true); /*Obtain a SAX Parser */ SAXParser saxParser = parserFactory.newSAXParser(); .......... } By default, the startElement() and endElement() methods take the namespaceURI as one of their parameters. Therefore, an application that needs to process namespace information can use it directly. For the MyXMLHandler application, you will display the namespaces. To do so, add the lines listed in bold in Listing 4.12. Listing 4.12 Displaying Namespacespublic void startElement(String namespaceURI, String localName, String qualifiedName, Attributes elementAttributes) { System.out.println("Start Element-> "+" ["+namespaceURI+"]"+qualifiedName); /* Get the index of price attributes*/ int indexOfPrice=elementAttributes.getIndex("price"); /* If a price attribute does not exist then all the attributes are printed out*/ /* Note that in the sample the attribute name is case sensitive so all attributes of carstereo get printed out*/ if(-1==indexOfPrice) printAllAttributes(elementAttributes); else System.out.println("\tPrice= "+ elementAttributes.getValue("price")); } public void endElement(String namespaceURI, String localName, String qualifiedName) { System.out.println("End Element-> "+" ["+namespaceURI+"]"+ qualifiedName); } NOTE The code discussed here is available in the example0404 folder. This folder also contains the sample CarParts.xml file. You can now compile and run the program. The output should be similar to the listing shown in Listing 4.13, with the namespace occurrences displayed in bold. Listing 4.13 Output of MyXMLHandler with Namespace ProcessingVersion 0404.0 of MyXMLHandler in example0404 Start Document: -----Reading CarParts.xml with MyXMLHandler------ Start Element-> []carparts Start Element-> []engines Start Element-> [http://enginesonline.com]engine Start Element-> [http://enginesonline.com]mpfiengine Attribute: [http://enginespecs.com]enginespecs:documentation = ALFA37D Start Element-> [http://enginesregistration.com]registration:number End Element-> [http://enginesregistration.com]registration:number End Element-> [http://enginesonline.com]mpfiengine End Element-> [http://enginesonline.com]engine Start Element-> []engine Start Element-> []mviengine End Element-> []mviengine End Element-> []engine End Element-> []engines Start Element-> []carbody End Element-> []carbody Start Element-> []wheel End Element-> []wheel Start Element-> []carstereo End Element-> []carstereo End Element-> []carparts End Document: ----------------Finished Reading the document------------------- |