2

我有一个使用 XMLStreamReader 对象从中读取的 xml 文件。所以我会保持简单:

让我们以这个 xml 示例为例:

<mySample xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" attribute1="value1"/>

所以我需要的是获取值(作为字符串)“xmlns:xsi”并获取值(也作为字符串)“ http://www.w3.org/2001/XMLSchema-instance

我确实尝试过这样的测试:

if (reader.getEventType() != XMLStreamConstants.NAMESPACE){
       attributeName = reader.getAttributeLocalName(i);
       attributeValue = reader.getAttributeValue(i);
}
else{
       attributeName = reader.getNamespacePrefix(i) + reader.getNamespaceURI(i);
       attributeValue = reader.getAttributeValue(i);
}

但它没有用。

显然我错过了这个 API 的新手,所以任何帮助都会非常受欢迎。

4

1 回答 1

6

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 报告命名空间声明,它不是一个或另一个,而是两者兼而有之。

于 2014-08-05T10:33:16.357 回答