我可以使用JAXB将所有命名空间定义放到顶级元素中

时间:2011-05-24 09:06:13

标签: java xml namespaces jaxb xml-namespaces

使用手工编写的代码我的xml是这样的:

    <?xml version="1.0" encoding="UTF-8"?>
    <metadata xmlns="http://musicbrainz.org/ns/mmd-1.0#" 
    xmlns:ext="http://musicbrainz.org/ns/ext-1.0#">
    <artist-list offset="0" count="8">
    <artist type="Person" id="00ed154e-8679-42f0-8f42-e59bd7e185af" 
    ext:score="100">

现在使用更好的JAXB但是虽然xml完全有效但我需要强制它将元数据元素中的xmlns:ext =“http://musicbrainz.org/ns/ext#-1.0”放入其中与我无法控制的客户端代码兼容的艺术家元素。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <metadata xmlns="http://musicbrainz.org/ns/mmd-1.0#">
    <artist-list offset="0" count="4">
    <artist type="Person" id="00ed154e-8679-42f0-8f42-e59bd7e185af" 
    ext:score="100" xmlns:ext="http://musicbrainz.org/ns/ext#-1.0">

请问这可以吗?

编辑:使用String替换它,因为我只需处理一个特定的情况

    String xml = sw.toString();

    //Remove extension namespace definition
    xml=xml.replace("xmlns:ext=\"http://musicbrainz.org/ns/ext#-1.0","");

    //Add it to the top instead
    xml=xml.replace("<metadata xmlns=\"http://musicbrainz.org/ns/mmd-1.0#\">",
                     "<metadata xmlns=\"http://musicbrainz.org/ns/mmd-1.0#\" xmlns:ext=\"http://musicbrainz.org/ns/ext-1.0#\">");

    //Now write out to the proper output stream
    out.write(xml);

2 个答案:

答案 0 :(得分:1)

我认为没有办法使用JAXB,但这是使用Dom4J的快速后处理器:

public static void moveNameSpacesToRoot(Document document) {
    final Element rootElement = document.getRootElement();
    moveNameSpacesToRootElement(rootElement, rootElement);
}

@SuppressWarnings("unchecked")
private static void moveNameSpacesToRootElement(
    Element thisElement, Element rootElement) {
    if (!thisElement.equals(rootElement)) {
        Namespace namespace = thisElement.getNamespace();
        if (!namespace.equals(Namespace.NO_NAMESPACE)) {
            Namespace existingRootNamespace = 
                  rootElement.getNamespaceForPrefix(namespace.getPrefix());
            if (existingRootNamespace == null) {
                rootElement.add(namespace);
            }
            thisElement.remove(namespace);
        }
    }
    for (Element child : (List<Element>) thisElement.elements()) {
        moveNameSpacesToRootElement(child, rootElement);
    }
}

哦,我刚刚意识到你需要属性,而不是元素。但是,这种变化是微不足道的,所以我会留给你。

答案 1 :(得分:0)

JAXB中至少没有文档记录的功能来控制应该放置名称空间前缀声明的元素。但是,您应该知道两个XML片段在语义上是相同的(如果在同一节点或任何祖先上声明名称空间前缀并不重要),因此您应该选择修复损坏的客户端代码或让某人控制客户端代码来修复它。