当前位置: 首页 > 知识库问答 >
问题:

JAXB和名称空间相关问题

谈萧迟
2023-03-14

在marshall一个JAXB类之后,我有下面的XML:

<?xml version="1.0" encoding="UTF-8"?>
<foo:Object xsi:schemaLocation="http://foo.com/ http://foo.com/foo.xsd" 
xmlns:ns0="http://lipsum.com/bar" xmlns:foo="http://foo.com/" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <foo:Some attr1="601"/>
   <foo:Others>
      <bar:Another xsi:schemaLocation="http://lipsum.com/bar 
      http://lipsum.com/bar.xsd" xmlns:bar="http://lipsum.com/bar">
         <bar:SomeOther attr2="01"/>
      </bar:Another>
  </foo:Others>
</foo:Object>

这个

    @XmlAnyElement(lax = true)
    @XmlElementRefs({
         @XmlElementRef(name="Another", type=Another.class, required=false)
    })
    protected List<Object> any;

它可能包含未知数量的具有自己名称空间的其他元素。

问题:

当我马歇尔的一些。类对象,jaxb将另一个的名称空间。类作为ns0导入根元素,因为我得到

这是一个问题,因为

我需要@XmlElementRefs和@XmlElementRef注释,因为我需要从json转换为XML,并且Jackson需要知道“任何”列表可能具有的类型。

我如何告诉JAXB Oracle/Moxy实现:

1.- Ignore the namespaces from @XmlElementRef classes during the marshalling.
2.- Remove the not used namespaces aka NS[0-9] prefixes from the root element.

任何帮助都会得到赞赏。

共有1个答案

傅阿苏
2023-03-14

为了以防有人需要,我找到了一种方法来删除不需要的名称空间,这个技巧来自XMLStreamWriter

步骤 1.- 创建一个 WrapperXMLStreamWriter 类,用于包装 XMLStreamWriter。

public class WrapperXMLStreamWriter implements XMLStreamWriter {
    private final XMLStreamWriter writer;

    public WrapperXMLStreamWriter(XMLStreamWriter writer) {
        this.writer = writer;
    }

    /* (non-Javadoc)
     * @see javax.xml.stream.XMLStreamWriter#writeStartElement(java.lang.String)
     */
    @Override
    public void writeStartElement(String localName) throws XMLStreamException {
        // for each overloaded method call to writer do the method
        writer.writeStartElement(localName);
    }

     /* (non-Javadoc)
     * @see javax.xml.stream.XMLStreamWriter#writeNamespace(java.lang.String, java.lang.String)
     */
    @Override
    public void writeNamespace(String prefix, String namespaceURI) throws XMLStreamException {
        // Here is the trick
        if(!prefix.startsWith("ns")){
            writer.writeNamespace(prefix, namespaceURI);
        }
    }

    ...
}

步骤2.-像往常一样装一个编组员

Map<String,String> prefixes = new HashMap<String, String>();

// 
prefixes.put("http://www.w3.org/2001/XMLSchema-instance","xsi");
prefixes.put("http://foo.com/", "foo");

Marshaller marshaller =  AppContextTool.getInstance().getContextForFoo().createMarshaller();

// 
marshaller.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapperImpl(prefixes));
marshaller.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "http://foo.com/ http://foo.com/foo.xsd");

3.-使用第一步的给定XMLStreamWriter对Foo实例进行马歇尔处理

Foo foo = new Foo();

ByteArrayOutputStream xml= new ByteArrayOutputStream();
try {
    XMLStreamWriter writer = 
                new WrapperXMLStreamWriter((XMLStreamWriter) XMLOutputFactory.newInstance().createXMLStreamWriter(xml, "UTF-8"));

    marshaller.marshal(foo, writer);
} catch (XMLStreamException | FactoryConfigurationError e) {
    e.printStackTrace();
}

4.-结果:

<?xml version="1.0" encoding="UTF-8"?>
<foo:Object xsi:schemaLocation="http://foo.com/ http://foo.com/foo.xsd" 
 xmlns:foo="http://foo.com/" 
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <foo:Some attr1="601"/>
        <foo:Others>
            <bar:Another xsi:schemaLocation="http://lipsum.com/bar 
  http://lipsum.com/bar.xsd" xmlns:bar="http://lipsum.com/bar">
          <bar:SomeOther attr2="01"/>
       </bar:Another>
  </foo:Others>
  </foo:Object>

没有更多的NS命名空间,希望这对某人有帮助。

 类似资料:
  • 问题内容: 给定初始XML(BPEL)文件: 我编写了一个使用JAXB的函数,以修改XML内的某些数据。功能如下: 与JAXB相关的编辑之后的结果XML为: 不幸的是,由于解析新XML时XML解析器崩溃,因此生成的XML不符合我们的应用程序。 所以: 如何在生成的XML中删除名称空间? 如何在初始XML文件中保留相同的标头(缺少)? 谢谢! 问题答案: 如果使用MOXy JAXB实现,则可以执行以

  • 问题内容: 除了包级别注释外,还有其他方法可以使用注释来控制自定义名称空间前缀。 可以在元素级别完成吗?也可能有一个带有多个前缀的名称空间吗? 问题答案: 您实际上想做什么?为什么名称空间前缀对您很重要? 对于命名空间前缀,没有标准的元素级注释。 我知道的控制名称空间前缀的选项是: 你已经提到过。 提供习俗。 XML的低级处理(例如,在StAX,SAX或DOM级别)。 我也可以想象: / 通常使用

  • 例如,一个XML属性值是,但名称空间前缀“repository”从未在数据集中定义。(不要紧,提供商的最佳实践建议定义它!) 所以当我去解封一个示例集时,具有指定前缀的QName属性(在我上面的示例中为“Repository”)是空的!所以看起来JAXB正在“抛出”那些具有未定义名称空间前缀的属性QName值。我很惊讶,它甚至没有保留当地的名字。 理想情况下,我希望保持该值原样,但看起来我无法在绑

  • 我有情况, 有一个sample.xsd(旧版本-没有命名空间)。为同一个XSD文件使用XJC生成JAXB类。我得到了一个使用JAXB类基于XSD解封XML数据文件的示例。sample.xsd文件已更改(新版本-添加的命名空间)。再次为新的XSD文件使用XJC生成JAXB类。该示例已更新,现在可以用于新的XSD文件 现在我有一个情况,我正在获取基于旧XSD的XML数据文件,我想使用更新的示例文件来解

  • 问题内容: 这是我的xml,需要将其转换为Java。我用过jaxb 并引发以下异常javax.xml.bind.UnmarshalException:意外元素(uri:“ http://www.ae.com/Event/Load ”,本地:“ Order”)。期望的元素是<{} lm:Order> 这是我的解组代码 订购Pojo班 您能否也帮助我阅读,当前正在读取文件,需要读取为XML Strin

  • 我对C++不是很熟悉,这是我第一次使用的不仅仅是名称空间std。下面的有什么区别? VS 在这两个之后,我现在似乎可以创建一个MyClass对象了。一种方式比另一种好吗?另外,如果我都不这样做,我还可以通过每次需要时在MyNamespace::MyClass之前附加MyClass来引用MyClass吗? 接下来,如果我使用第二个选项转发declare,我还需要吗?在我(不是很好)的理解中,在C++