开发者

Can I put all namspace definition to top level element with JAXB

Using handcrafted code my xml was like this:

    <?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">

Now using JAXB which is much better but although the xml is perfectly valid I need to force it to put the xmlns:ext="http://musicbrainz.org/ns/ext#-1.0" within the metadata element not the artist element for compatability with client code that I have no control over.

    <?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">

Can this be done please ?

EDIT:Worked round it with String replace because I only have to deal with one specific case

    String xml = sw.toString();

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

    //Add it 开发者_如何学Goto 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);


I don't think there's a way to do it using JAXB, but here's a quick post-processor using 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);
    }
}

Oh, I just realized that you need attributes, not elements. However, the change is trivial, so I'll leave that for you.


There is at least no documented feature in JAXB to control on which element the namespace prefix declaration should be placed. You should however be aware that the two XML snippets are semantically identical (it does not matter if the namespace prefix is declared on the same node or on any ancestor), so you should opt to fix the broken client code or get someone with control of the client code to fix it.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜