代码之家  ›  专栏  ›  技术社区  ›  Garet

要映射的JAXB节点

  •  0
  • Garet  · 技术社区  · 7 年前

    我有如下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节点和类型节点映射到具有相同名称的属性,项目内的所有其他内容都添加到映射中。

    我试着用注释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找到每个剩余的元素,用适配器解析它,并将结果添加到集合中。

    有什么方法可以扭转这种局面吗?

    1 回复  |  直到 7 年前
        1
  •  1
  •   Thomas Fritsch    7 年前

    像你一样,我没有成功地写一个 XmlAdapter .

    Item 类声明a List<Element> 注释为 @XmlAnyElement , 因此JAXB将使用它进行编组/解编。

    Map<String, String> 但注释为 @XmlTransient

    最后实现一个私有方法 afterUnmarshal(Unmarshaller unmarshaller, Object parent) 如中所述 Unmarshal Event Callbacks JAXB将在适当的时候调用此方法。

    beforeMmarshal(Marshaller marshaller) 在那里你从 映射(<);字符串,字符串> 列表(<);元素> . Marshal Event Callbacks

    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);
                }
            }
        }
    
    }