JSR-173 规范(Java 的 Stax API)关于 NAMESPACE 事件声明如下:
命名
空间 命名
空间声明也可以存在于 StartElement 之外,并且可以作为独立的信息项进行报告。通常,命名空间是作为 StartElement 事件的一部分报告的。当命名空间是 XQuery 或 XPath 表达式的结果时,它们可能被报告为独立事件。
因此,如果您正在查看命名空间事件,您很可能应该检查StartElement
事件并检查它们。再一次,从规范:
可以使用以下方法访问命名空间:
int getNamespaceCount();
String getNamespacePrefix(int index);
String getNamespaceURI(int index);
只有在当前 StartElement 上声明的命名空间可用。该列表不包含先前声明的命名空间,也不会删除重新声明的命名空间。
在解析过程中的任何时候,您都可以获得当前完整的命名空间上下文:
当前状态的命名空间上下文可通过调用
XMLStreamReader.getNamespaceContext()
或
获得StartElement.getNamespaceContext()
。这些方法返回
javax.xml.namespace.NamespaceContext
接口的一个实例。
这就是理论:大多数命名空间声明来自 START_ELEMENT,有些可能是独立的。
在实践中,我从未遇到过 API 在读取文件时报告的 NAMESPACE 事件。它几乎总是作为 START_ELEMENT 的一部分报告(并在相应的 END_ELEMENT 中重复),因此如果您对命名空间声明感兴趣,则必须检查 START_ELEMENT。例如,从您的文档开始:
String xml = "<?xml version=\"1.0\" encoding=\"utf-8\" ?><mySample xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" attribute1=\"value1\"/>";
XMLStreamReader reader = XMLInputFactory.newFactory().createXMLStreamReader(new StringReader(xml));
while (reader.hasNext()) {
int event = reader.next();
if (XMLStreamConstants.START_ELEMENT == event) {
if (reader.getNamespaceCount() > 0) {
// This happens
System.out.println("ELEMENT START: " + reader.getLocalName() + " , namespace count is: " + reader.getNamespaceCount());
for (int nsIndex = 0; nsIndex < reader.getNamespaceCount(); nsIndex++) {
String nsPrefix = reader.getNamespacePrefix(nsIndex);
String nsId = reader.getNamespaceURI(nsIndex);
System.out.println("\tNamepsace prefix: " + nsPrefix + " associated with URI " + nsId);
}
}
} else if(XMLStreamConstants.NAMESPACE == event) {
// This almost never happens
System.out.println("NAMESPACE EVENT");
}
}
将产生:
元素开始: mySample ,命名空间计数为:1
Namepsace 前缀:与 URI http://www.w3.org/2001/XMLSchema-instance关联的 xsi
底线:您应该检查 NAMESPACE 和 START_ELEMENT 事件,即使大多数时候,您只会有 START_ELEMENT 报告命名空间声明,它不是一个或另一个,而是两者兼而有之。