Reputation: 28568
I have an xml document as
<fr:frame xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:fr="http://mebigfatguy.com/ds/frame"
xmlns:comp="http://mebigfatguy.com/ds/component"
xmlns:cont="http://mebigfatguy.com/ds/container"
xmlns:b="http://mebigfatguy.com/ds/button">
<comp:preferredSize>500,300</comp:preferredSize>
<cont:childComponent>
<cont:name>CENTER</cont:name>
<cont:component xsi:type="b:Button">
<comp:name>Click Me</comp:name>
</cont:component>
</cont:childComponent>
<fr:title>Example</fr:title>
</fr:frame>
where b:Button is an xml extension type of cont:component
In my startElement call, i receive a uri of http://mebigfatguy.com/ds/container and qname of cont:component as expected. The xsi:type="b:Button" is found in the attributes, also as expected.
The question I have is how does one lookup the namespace uri of b:Button as retrieved from the xsi:type attribute. Do i have to manage the xmlns attributes manually myself? or is there a built in way to resolve what the uri is?
Upvotes: 1
Views: 770
Reputation: 3020
Yes. you have to do lookup namespace uri for b:Button
and you have to manage xmlns attributes using org.xml.sax.helpers.NamespaceSupport. It is little tricky to populate NamespaceSupport
properly.
Below is the sample code which prints xsi:type
value with uri
and localname
:
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.NamespaceSupport;
import javax.xml.XMLConstants;
import javax.xml.parsers.SAXParserFactory;
/**
* @author Santhosh Kumar Tekuri
*/
public class XSIHandler extends DefaultHandler{
private boolean needNewContext;
private NamespaceSupport nsSupport;
@Override
public void startDocument() throws SAXException{
nsSupport = new NamespaceSupport();
needNewContext = true;
super.startDocument();
}
@Override
public void startPrefixMapping(String prefix, String uri) throws SAXException{
if(needNewContext){
nsSupport.pushContext();
needNewContext = false;
}
nsSupport.declarePrefix(prefix, uri);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException{
if(needNewContext)
nsSupport.pushContext();
needNewContext = true;
String xsiType = atts.getValue(XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, "type");
if(xsiType!=null){
String prefix, suffix;
int colon = xsiType.indexOf(':');
if(colon==-1){
prefix = "";
suffix = xsiType;
}else{
prefix = xsiType.substring(0, colon);
suffix = xsiType.substring(colon+1);
}
System.out.println("xsi:type for " + qName + " is uri: " + nsSupport.getURI(prefix) + " localName: " + suffix);
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException{
nsSupport.popContext();
}
}
here is the driver function:
public static void main(String[] args) throws Exception{
SAXParserFactory factory = SAXParserFactory.newInstance();
factory.setNamespaceAware(true);
factory.newSAXParser().parse("test.xml", new XSIHandler());
}
the output is:
xsi:type for cont:component is uri: http://mebigfatguy.com/ds/button localName: Button
Upvotes: 0
Reputation: 32980
SAX reports the namespace URI of elements and attributes in ContentHandler.startElement
but does not provide a general method to translate a prefix into a namespace URI during parsing.
For that you have to implement startPrefixMapping
and endPrefixMapping
in your ContentHandler
and keep track of the active bindings. (If done right this must also cover namespace undeclarations).
Upvotes: 2