【问题标题】:Can I put all namspace definition to top level element with JAXB我可以使用 JAXB 将所有命名空间定义放到顶级元素中吗
【发布时间】:2011-08-31 18:36:04
【问题描述】:

使用手工编写的代码,我的 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 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);

【问题讨论】:

  • 用字符串替换解决了它
  • 如果现有元素中有额外的空格,您的替换将不起作用。
  • true 但初始 xml 是由 jaxb 生成的,并且始终生成相同的,因此在这种情况下始终有效。

标签: java xml namespaces jaxb xml-namespaces


【解决方案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);
    }
}

哦,我刚刚意识到你需要的是属性,而不是元素。但是,更改是微不足道的,所以我将其留给您。

【讨论】:

  • 谢谢,这是一个选项,但由于我真的不想引入依赖关系并且 xml 作为字符串发送回来,我可能只是应用正则表达式来修复输出
  • @user 我明白了,但这肯定是一个正则表达式:-)
【解决方案2】:

至少在 JAXB 中没有记录的特性来控制命名空间前缀声明应该放置在哪个元素上。但是,您应该知道这两个 XML sn-ps 在语义上是相同的(命名空间前缀是在同一个节点上还是在任何祖先上声明都无关紧要),因此您应该选择修复损坏的客户端代码或让某人使用控制客户端代码来修复它。

【讨论】:

  • 是的,正如我上面所说的,我知道所有这些,但是纠正第三方客户端需要时间,所以我现在需要修复现有客户端的所有用户z(我没有写)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-10-17
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多