Jackson XML - 使用命名空间前缀反序列化 XML

Posted

技术标签:

【中文标题】Jackson XML - 使用命名空间前缀反序列化 XML【英文标题】:Jackson XML - deserializing XML with namespace prefixes 【发布时间】:2013-05-02 19:25:13 【问题描述】:

我正在使用 Jackson XML 插件 (https://github.com/FasterXML/jackson-dataformat-xml),我不确定它是否受支持,但我想知道是否可以使用命名空间前缀序列化和反序列化 XML,如下所示:

<name:Foo>
  <name:Bar>
    <name:x>x</name:x>
    <name:y>y</name:y>
  </name:Bar>
</name:Foo>

我可以像这样使用 Jackson 的插件生成这种类型的 XML:

@JacksonXmlProperty(localName="name:Bar")
public Bar getBar() 
    return bar;

但是,我找不到将我的 POJO 配置为从生成的 XML 反序列化的方法。请看以下示例代码:

public class Bar
    @JacksonXmlProperty(localName="name:x")
    public String x = "x";
    @JacksonXmlProperty(localName="name:y")
    public String y = "y";


@JacksonXmlRootElement(localName="name:Foo")
    public class Foo
        private Bar bar;

        @JacksonXmlProperty(localName="name:Bar")
        public Bar getBar() 
           return bar;
        

        public void setBar(Bar bar) 
            this.bar = bar;
           


public class TestDeserialization 

    public static void main(String[] args) throws Exception 
        Foo foo = new Foo();
        foo.setBar(new Bar());

        XmlMapper xmlMapper = new XmlMapper();
        String xml = xmlMapper.writerWithDefaultPrettyPrinter().writeValueAsString(foo);
        System.out.println(xml);
        System.out.println("XML Desearialzing....");
        Foo foo2= xmlMapper.readValue(xml, Foo.class);
        System.out.println(xmlMapper.writeValueAsString(foo2));
     

尝试运行这个测试给了我一个例外:

Exception in thread "main" java.io.IOException: com.ctc.wstx.exc.WstxParsingException: Undeclared namespace prefix "name"

这是可以理解的,但我想知道是否有办法让它与 Jackson XML 一起使用?

【问题讨论】:

【参考方案1】:

虽然这是一篇旧文章,但我刚刚遇到了这个问题,匹配我的服务调用所需的 XML 的唯一解决方案是这样的,其中命名空间声明也使用前缀。

@JacksonXmlRootElement(localName = "entry")
abstract class BaseEntry implements Serializable  
    private static final long serialVersionUID = 6835429382441010779L;
    private final String xmlns = "com.foo.bar"; 
    private String type;
    
    protected BaseEntry(String type) 
        this.type = type;
    

    @JacksonXmlProperty(isAttribute = true)
    public String getType() 
        return type;
    
    
    @JacksonXmlProperty(localName = "xmlns:ns2", isAttribute = true)
    public String getXmlns() 
        return xmlns;
    

这会产生类似:

<entry type="com.foo.bar" xmlns:ns2="com.foo.bar">
...
</entry>

【讨论】:

【参考方案2】:

JacksonXmlProperty 注释具有属性namespace。用它来定义namespace

public class Bar 
    @JacksonXmlProperty(namespace = "name",localName="x")
    public String x = "x";
    @JacksonXmlProperty(namespace = "name",localName="y")
    public String y = "y";
 

@JacksonXmlRootElement(namespace = "name", localName = "Foo")
public class Foo 
   private Bar bar;

   @JacksonXmlProperty(namespace = "name", localName = "Bar")
   public Bar getBar() 
      return bar;
   

   public void setBar(Bar bar) 
      this.bar = bar;
   

【讨论】:

使用上述命名空间配置会生成以下 XML:&lt;Foo xmlns="name"&gt; &lt;Bar&gt; &lt;x&gt;x&lt;/x&gt; &lt;y&gt;y&lt;/y&gt; &lt;/Bar&gt; &lt;/Foo&gt; - 我可以假设这与我之前提供的示例 XML 是同义词吗? @jtyler 是的,这个 xml 和你的很相似 @Ilya:我面临与这个问题相同的问题。我也收到&lt;Foo xmlns="name"&gt; &lt;Bar&gt; &lt;x&gt;x&lt;/x&gt; &lt;y&gt;y&lt;/y&gt; &lt;/Bar&gt; &lt;/Foo&gt;。这和&lt;name:foo&gt;&lt;/name:foo&gt; 有什么区别??前缀没有被添加。能详细点吗? @SiddharthTrikha 我的理解是,要么您直接使用带有名称的 xmlns,如您所说的 这意味着 Foo 标签是在“名称”命名空间中定义的,或者您给出一个此命名空间的别名并像 一样使用它

以上是关于Jackson XML - 使用命名空间前缀反序列化 XML的主要内容,如果未能解决你的问题,请参考以下文章

XML 序列化和命名空间前缀

C# 使用多个可能的命名空间反序列化 xml

反序列化 xml,包括命名空间

在不修改 C# XSD 类的情况下向 XML 序列化添加前缀和命名空间

C# 在忽略命名空间的同时反序列化 xml

由于命名空间而无法反序列化 xml