简体   繁体   English

如何使用XMLStreamReader读取xml中的名称空间?

[英]How to read namespace as it is in a xml using XMLStreamReader?

I have an xml file from which i read using an XMLStreamReader object. 我有一个使用XMLStreamReader对象从中读取的xml文件。 So i'll keep it simple : 因此,我将使其保持简单:

Let's take this xml example : 让我们以这个xml示例为例:

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

So what i need is to get the value (as a String) "xmlns:xsi" and get the value (as a String also) " http://www.w3.org/2001/XMLSchema-instance " 因此,我需要获取值(作为字符串)“ xmlns:xsi”并获取值(也作为字符串)“ http://www.w3.org/2001/XMLSchema-instance

I did try to have a test like this : 我确实尝试过这样的测试:

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);
}

But it did not work. 但这没有用。

Obviously i missed something being a newbie to this API, so any help would be very welcome. 显然,我错过了一些成为该API的新手的知识,因此非常欢迎您提供任何帮助。

The JSR-173 specification (Stax API for Java) states the following regarding the NAMESPACE event : JSR-173规范(用于Java的Stax API)针对NAMESPACE事件规定了以下内容:

Namespace 命名空间
Namespace declarations can also exist outside of a StartElement and may be reported as a standalone information item. 命名空间声明也可以存在于StartElement之外,并且可以作为独立的信息项进行报告。 In general Namespaces are reported as part of a StartElement event . 通常,将命名空间报告为StartElement事件的一部分 When namespaces are the result of an XQuery or XPath expression they may be reported as standalone events. 当名称空间是XQuery或XPath表达式的结果时,它们可能被报告为独立事件。

So if you are looking at namespace events, you should most probably be checking StartElement events, and inspect them. 因此,如果您正在查看名称空间事件,则很可能应该检查StartElement事件并进行检查。 Once again, from the spec : 再次,从规范:

Namespaces can be accessed using the following methods: 可以使用以下方法访问名称空间:

int getNamespaceCount(); int getNamespaceCount();
String getNamespacePrefix(int index); 字符串getNamespacePrefix(int index);
String getNamespaceURI(int index); 字符串getNamespaceURI(int index);

Only the namespaces declared on the current StartElement are available. 仅在当前StartElement上声明的名称空间可用。 The list does not contain previously declared namespaces and does not remove redeclared namespaces. 该列表不包含以前声明的名称空间,也不会删除重新声明的名称空间。

At any point during the parsing, you can get the current complete namespace context : 在解析过程中的任何时候,您都可以获取当前完整的名称空间上下文:

The namespace context of the current state is available by calling XMLStreamReader.getNamespaceContext() or StartElement.getNamespaceContext() . 通过调用XMLStreamReader.getNamespaceContext()StartElement.getNamespaceContext()可获得当前状态的名称空间上下文。 These methods return an instance of the javax.xml.namespace.NamespaceContext interface. 这些方法返回javax.xml.namespace.NamespaceContext接口的实例。

That's theory : most namespace declarations come from START_ELEMENT, some may come independently. 从理论上讲:大多数名称空间声明来自START_ELEMENT,有些可能独立出现。

In practice, I have never came accross a NAMESPACE event reported by the API when reading from a file. 实际上,从文件读取时,我从未遇到过API报告的NAMESPACE事件。 It's almost always reported as part of a START_ELEMENT (and repeated in the corresponding END_ELEMENT), so you must check START_ELEMENT if you are interested in namespace declaration. 它几乎总是作为START_ELEMENT的一部分报告的(并在相应的END_ELEMENT中重复),因此,如果您对名称空间声明感兴趣,则必须检查START_ELEMENT。 For example, starting with your document : 例如,从您的文档开始:

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");
  }
}

Will produce : 将产生:

ELEMENT START: mySample , namespace count is: 1 元素开始:mySample,名称空间计数为:1

Namepsace prefix: xsi associated with URI http://www.w3.org/2001/XMLSchema-instance Namepsace前缀:与URI http://www.w3.org/2001/XMLSchema-instance关联的xsi

Bottom line : you should check for NAMESPACE and START_ELEMENT events, even if most of times, you will only have START_ELEMENT reporting namespace declartions, it is not one or the other, it's both. 底线:您应该检查NAMESPACE和START_ELEMENT事件,即使在大多数情况下,您将只具有START_ELEMENT报告名称空间声明,这不是一个或另一个,而是两者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM