在使用流式解析器(SJSXP)进行验证之前尝试从XML中删除命名空间

时间:2014-04-04 20:00:11

标签: java xml xsd-validation stax sjsxp

我试图忽略XML文件的根元素中提供的命名空间,以便针对外部模式进行验证。不幸的是,我无法改变一些项目,因为这是一个交织在一起的遗留系统。

我已经读过(这里是SO)我应该能够在输入XML周围使用过滤器,但它似乎不起作用,感觉我错过了一些东西。当我运行验证时,我收到以下错误消息:

org.xml.sax.SAXParseException:cvc-elt.1:找不到元素'MY_ROOT_ELEMENT'的声明。

这是带有命名空间信息的XML文件的开头:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<MY_ROOT_ELEMENT xmlns="http://www.mycompany.net/somename" 
  schemaVersion="2.0.0" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.mycompany.net/somename 
                      myschema.xsd">
    ...
</MY_ROOT_ELEMENT>

以下是模式的伴随开头,其中定义了MY_ROOT_ELEMENT:

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
  elementFormDefault="qualified" 
  attributeFormDefault="unqualified">
    <xs:element name="MY_ROOT_ELEMENT" type="MY_ROOT_ELEMENT"/>

StreamReaderDelegate,用于忽略命名空间:

private static final class NoNamespaceStreamReaderDelegate extends StreamReaderDelegate {
    NoNamespaceStreamReaderDelegate(XMLStreamReader reader) {
        super(reader);
    }

    @Override
    public NamespaceContext getNamespaceContext() {
        return super.getNamespaceContext();
    }

    @Override
    public int getNamespaceCount() {
        return 1;
    }

    @Override
    public String getNamespacePrefix(int index) {
        if (index == 0) {
            return "xsi";
        }

        throw new NullPointerException();
    }

    @Override
    public String getNamespaceURI() {
        return null;
    }

    @Override
    public String getNamespaceURI(String prefix) {
        if ("xsi".equals(prefix)) {
            return XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
        }
        return null;
    }

    @Override
    public String getNamespaceURI(int index) {
        if (index == 0) {
            return XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI;
        }
        return null;
    }
}

最后,如何调用验证:

// reads from the classpath
XMLStreamReader reader = createReaderFromSource();
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = sf.newSchema(inputSource.getSchema());
Source readerSource = new StAXSource(new NoNamespaceStreamReaderDelegate(reader));

Validator validator = schema.newValidator();
validator.validate(readerSource);

1 个答案:

答案 0 :(得分:0)

为后人发布此信息。

似乎答案是设置&#34; IS_NAMESPACE_AWARE&#34; XMLInputFactory上的属性为false,然后使用StreamReaderDelegate确保忽略xsi:schemaLocation。许多包装器库都是这个API的一部分,但对于the default StAX implementation,您需要设置属性。

一旦我宣布了以下内容并实施了代表,一切都像魅力一样。

XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, Boolean.TRUE);