【问题标题】:JAXB nodes to map要映射的 JAXB 节点
【发布时间】:2017-08-09 10:56:46
【问题描述】:

我有一个如下的 XML 文件:

<root>
  <item>
    <id>my id</id>
    <type>my type</id>
    <key1>value1</key1>
    <key2>value1</key2>
    <key3>value1</key3>
  </item>

  <item>
    <id>my id</id>
    <type>my type</type>
    <other-key1>value1</other-key1>
    <other-key2>value1</other-key2>
  </item>

  (...)

</root>

我想在这样的类上解析 XML:

public class Item {
    private String id;

    private String type;

    private Map<String, String> values;
}

其中 id 节点和 type 节点映射到同名的属性,并且项目内的所有其他内容都添加到映射中。

我已经尝试使用注释 XmlJavaTypeAdapter 和 XmlAnyElement 编写一个类,但这并不符合我的预期:

(...)

public class Item {
    @XmlElement
    private String id;

    @XmlElement
    private String type;

    @XmlAnyElement
    @XmlJavaTypeAdapter(MapAdapter.class)
    private Map<String, String> values;
}


public class MapAdapter extends XmlAdapter<Object, Map<String, String>> {
    @Override
    public Object marshal(Map<String, String> v) throws Exception {
    }

    @Override
    public Map<String, String> unmarshal(Object v) throws Exception {
        // v is a node instead an array of nodes.
        // I want to get an array of nodes to convert them to a map.
        //
        // eg:
        //  
        //   key1 -> value1
        //   key2 -> value2
        //   key3 -> value3
        //
    }

知道我怎么能得到这个吗?

更新

澄清我的问题:

我的问题是我想在地图中解组的元素不在包装器内,它们与同一级别的其他元素混合在一起。

我尝试使用 XmlAnyElement 和 XmlJavaTypeAdapter 来获取所有剩余元素的映射。然而,这些注释有一个隐含的顺序,我得到的是一个用适配器解析的元素集合:

XmlAnyElement 找到每个剩余元素,使用适配器对其进行解析并将结果添加到集合中。

有什么办法可以扭转这种情况吗?

我想获取所有剩余元素的集合,然后使用 XmlAdapter 解析该集合以获取地图。

【问题讨论】:

  • 这对我不起作用。我需要将元素列表解析为地图,并且带有元素的节点不在标签内:value1value2
  • 可能只是一个错字:但在您的Item 类中,您需要使用@XmlElement 注释idtype,而不是@XmlAttribute。否则,它们的 XML 也会在解组过程中出现在您的 @XmlAnyElement 中。
  • 这是一个拼写错误。已更改,谢谢!

标签: java xml jaxb


【解决方案1】:

和你一样,我没有成功写出XmlAdapter。 但是还有另一种可能的方法:

在你的Item 类中声明一个List&lt;Element&gt;@XmlAnyElement 注释, 以便 JAXB 将其用于编组/解组。

但你想要一个Map&lt;String, String&gt;。因此你也宣告, 但使用 @XmlTransient 注释,以便 JAXB 不会将其用于编组/解组。

终于实现了一个私有方法afterUnmarshal(Unmarshaller unmarshaller, Object parent) 您将内容从List&lt;Element&gt; 铲到Map&lt;String, String&gt;。 如中所述 Unmarshal Event Callbacks JAXB 会在适当的时候调用这个方法。

如果需要编写 XML 文件 你可能还需要一个私有方法beforeMmarshal(Marshaller marshaller) 您将内容从Map&lt;String, String&gt; 铲回List&lt;Element&gt;。 如中所述 Marshal Event Callbacks JAXB 会在适当的时候调用这个方法。

public class Item {

    @XmlElement
    private String id;

    @XmlElement
    private String type;

    @XmlAnyElement
    private List<Element> otherElements;

    @XmlTransient  // don't participate in JAXB marshalling/unmarshalling
    private Map<String, String> values;

    @SuppressWarnings("unused")   // called only by JAXB
    private void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
        values = new HashMap<>();
        if (otherElements != null) {
            for (Element element : otherElements) {
                String key = element.getNodeName();
                String value = element.getFirstChild().getNodeValue();
                values.put(key, value);
            }
        }
    }

}

【讨论】:

  • 这正是我想要的!我不知道 JAXB 回调。谢谢!
猜你喜欢
  • 2012-01-29
  • 2012-07-04
  • 2014-04-22
  • 2013-10-10
  • 1970-01-01
  • 1970-01-01
  • 2011-03-27
  • 2011-10-12
相关资源
最近更新 更多