开发者

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

开发者 https://www.devze.com 2023-03-08 04:14 出处:网络
Using handcrafted code my xml was like this: <?xml version=\"1.0\" encoding=\"UTF-8\"?> <metadata xmlns=\"http://musicbrainz.org/ns/mmd-1.0#\"

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

精彩评论

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

关注公众号