【问题标题】:JAXB and namespaces related issueJAXB 和命名空间相关问题
【发布时间】:2018-05-01 13:42:30
【问题描述】:

编组 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>

jaxb 类中的 元素声明为:

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

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

问题:

当我编组 Some.class 对象时,jaxb 将 Another.class 的命名空间作为 ns0 放入根元素中,因为我从另一个方法中将 编组为元素,其中包含它们的命名空间我不'不需要再次将它放入根元素中。

这是一个问题,因为不需要 ,所以如果我将 Some.class 对象与一个空列表编组,我将始终拥有 xmlns: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.

我们将不胜感激。

【问题讨论】:

    标签: xml namespaces jaxb moxy jaxb2


    【解决方案1】:

    以防万一有人需要这个,我有一种方法来删除不需要的命名空间,这个技巧由 XMLStreamWriter 提供

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

    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 命名空间,希望这对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-06-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-21
      • 2016-09-21
      相关资源
      最近更新 更多