XML:在SAX内容处理程序

时间:2015-07-26 03:18:52

标签: java xml xsd sax

我有一个xml文档

<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>

其中b:Button是cont:component

的xml扩展类型

在我的startElement调用中,我按预期收到了一个http://mebigfatguy.com/ds/container的uri和cont:component的qname。 xsi:type =“b:Button”可以在属性中找到,也可以按预期找到。

我遇到的问题是如何从xsi:type属性中检索b:Button的名称空间uri。我是否必须自己手动管理xmlns属性?或者是否有内置的方法来解决uri是什么?

2 个答案:

答案 0 :(得分:2)

SAX报告ContentHandler.startElement中元素和属性的名称空间URI,但没有提供在解析过程中将前缀转换为名称空间URI的一般方法。

为此,您必须在startPrefixMapping中实施endPrefixMappingContentHandler,并跟踪活动绑定。 (如果做得对,这还必须涵盖名称空间未声明)。

答案 1 :(得分:0)

是。您必须为b:Button执行查找命名空间uri,并且必须使用org.xml.sax.helpers.NamespaceSupport管理xmlns属性。正确填充NamespaceSupport有点棘手。

以下是使用xsi:typeuri打印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();
    }
}

这是驱动程序功能:

public static void main(String[] args) throws Exception{
    SAXParserFactory factory = SAXParserFactory.newInstance();
    factory.setNamespaceAware(true);
    factory.newSAXParser().parse("test.xml", new XSIHandler());
}

输出是:

xsi:type for cont:component is uri: http://mebigfatguy.com/ds/button localName: Button