开发者

XML namespace defaulting/inheritance

In the below XML snippet what are the namespaces of a, c, d and e? Reference to doc开发者_运维技巧umentation or specifications would be appreciated.

<a xmlns="http://domain/a">
    <pre:b xmlns:pre="http://domain/b">
        <c/>
        <d xmlns="">
            <e/>
        </d>
    </pre:b>
</a>

Also, what Java frameworks respect the official namespace defaulting? I have tride org.w2c.* DOM packages, however it does not seem to resolve the namespace URI correctly? For example, something with similar functionality to.

String namespace = DocumentParser.parse().
                    getElement("a").
                    getElement("b").
                    getElement("c").
                    getNamespaceURI();


From what I can tell it would be as follows.

  • a will be http://domain/a as that is the default namespace
  • b will be http://domain/b as that is the defined namespace for b
  • c will be http://domain/a as that is the default namespace
  • d will be a blank/unset namespace due to re-setting of the namespace
  • e will be a blank/unset namespace, since it is nested inside of the new declaration

I am basing this off of this specification. Below is a summary quote to help as well.

If there is a default namespace declaration in scope, the expanded name corresponding to an unprefixed element name has the URI of the default namespace as its namespace name. If there is no default namespace declaration in scope, the namespace name has no value. The namespace name for an unprefixed attribute name always has no value. In all cases, the local name is local part (which is of course the same as the unprefixed name itself).


A namespace declared using xmlns="..." becomes the default for any elements within it (until the default is then redeclared in a deeper element, of course). So you end up with:

  • a uses http://domain/a (specified as a default)
  • b uses http://domain/b (specified, but not a default)
  • c uses http://domain/a (inherited from a)
  • d has no namespace (specified as a new default)
  • e has no namespace (inherited from d)

The relevant spec section is the XML names spec, section 6.2:

The scope of a default namespace declaration extends from the beginning of the start-tag in which it appears to the end of the corresponding end-tag, excluding the scope of any inner default namespace declarations. In the case of an empty tag, the scope is the tag itself.

A default namespace declaration applies to all unprefixed element names within its scope. Default namespace declarations do not apply directly to attribute names; the interpretation of unprefixed attributes is determined by the element on which they appear.

If there is a default namespace declaration in scope, the expanded name corresponding to an unprefixed element name has the URI of the default namespace as its namespace name. If there is no default namespace declaration in scope, the namespace name has no value. The namespace name for an unprefixed attribute name always has no value. In all cases, the local name is local part (which is of course the same as the unprefixed name itself).


To the best of my knowledge, all the standard XML APIs in Java support namespaces. Many of the APIs were written before namespaces were created (or became popular - I can no longer remember). You often need to enable support:

public class NS {
  private static void print(Node node) {
    Queue<Node> nodes = new LinkedList<Node>();
    nodes.add(node);
    while (!nodes.isEmpty()) {
      node = nodes.poll();
      NodeList list = node.getChildNodes();
      for (int i = 0; i < list.getLength(); i++) {
        nodes.add(list.item(i));
      }
      System.out.format("%s %s %s%n", node.getPrefix(), node.getLocalName(),
          node.getNamespaceURI());
    }
  }

  public static void main(String[] args) throws Exception {
    String xml = "<a xmlns=\"http://domain/a\">"
        + "<pre:b xmlns:pre=\"http://domain/b\">" + "<c/>" + "<d xmlns=\"\">"
        + "<e/>" + "</d>" + "</pre:b>" + "</a>";

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    Document doc = dbf.newDocumentBuilder().parse(
        new InputSource(new StringReader(xml)));
    print(doc.getDocumentElement());
  }
}

This code will print:

null a http://domain/a
pre b http://domain/b
null c http://domain/a
null d null
null e null
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜