如何使用Moxy将xml属性解析为键值

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用Moxy将xml属性解析为键值相关的知识,希望对你有一定的参考价值。

我试图使用MOXy解析下面的xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE dml>
<dml xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<content>
<entry>
      <namespace>
        <meta property="abc" content="abcd" />
        <meta property="xyz" content="xyzd" />
      </namespace>
    </entry>
    <entry>
      <namespace>
        <meta property="abc" content="pqr" />
        <meta property="xyz" content="xyzd" />
        <meta property="lmn" content="qwert" />
      </namespace>
    </entry>
</content>
</dml>

我想将元素'meta'的属性'property'和'content'解析为键值对。

我用下面的链接但没有运气。元图对我来说是空的。 http://blog.bdoughan.com/2013/06/moxys-xmlvariablenode-using-maps-key-as.html

这是我的课程。

  public static void parseDml(String dmlXmlFile) throws Exception {  

    DMLData dmlData = null;
    try 
    {
      JAXBContext jaxbContext = JAXBContext.newInstance(DMLData.class);
      unmarshaller = jaxbContext.createUnmarshaller();

      dmlData = (DMLData) unmarshaller.unmarshal(new File(dmlXmlFile));

      Marshaller marshaller = jaxbContext.createMarshaller();
      marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
      marshaller.marshal(dmlData, System.out);
    }
    catch (Exception e)
    {
      throw new Exception("Error while unmarshalling dml XML : " + e);
    }

  }

DML data.Java

@Getter
@NoArgsConstructor
@XmlRootElement(name = "dml")
@XmlAccessorType(XmlAccessType.FIELD)
public class DMLData
{

  @XmlPath("content/entry")
  private List<Entry> entry;


}

entry.Java

@XmlRootElement(name = "entry")
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
public class Entry
{

  @XmlPath("namespace/meta")
  @XmlJavaTypeAdapter(MapAdapter.class)
  private Map<String, String> map = new HashMap<String, String>();

}

meta.Java

@XmlRootElement(name = "boeXmlMeta")
@Getter
@XmlAccessorType(XmlAccessType.FIELD)
public class Meta
{

  private Map<String, String> boeXmlMeta = new HashMap<String, String>();

  @XmlPath("@property")
  private String property;

  @XmlPath("@content")
  private String content;

  public void setProperty(String model)
  {
    this.property = property;
  }

  public void setContent(String content)
  {
    this.content = content;
  } 
}

map adapter.Java

public class MapAdapter extends XmlAdapter<List<Meta>,HashMap<String,String>> {


  @Override
  public ArrayList<Meta> marshal(HashMap<String, String> map) throws Exception {
    ArrayList<Meta> list = new ArrayList<Meta>();
      for(Entry<String, String> entry : map.entrySet()) {
          Meta Meta = new Meta();
          Meta.setProperty(entry.getKey());
          Meta.setContent(entry.getValue());
          list.add(Meta);
      }
      return list;
  }

  @Override
  public HashMap<String, String> unmarshal(List<Meta> MetaList) throws Exception {
      HashMap<String, String> map = new HashMap<String, String>(MetaList.size());
      for(Meta Meta : MetaList)
      {
        map.put(Meta.getProperty() ,Meta.getContent());
      }
      return map;
  }

}

这是我得到的输出:

<?xml version="1.0" encoding="UTF-8"?>
<dml>
   <content>
      <entry/>
      <entry/>
   </content>
</dml>

任何帮助将不胜感激。

答案

我不认为需要XmlPath,好老的XmlElementXmlAttribute会做得很好。

entry.Java:

@XmlElement(name = "namespace")
@XmlJavaTypeAdapter(MapAdapter.class)
private Map<String, String> map = new HashMap<>();

meta.Java:

@XmlAttribute(name = "property")
private String property;

@XmlAttribute(name = "content")
private String content;

map adapter.Java:

public class MapAdapter extends XmlAdapter<Namespace, Map<String, String>> {

    @XmlRootElement(name = "meta")
    @XmlAccessorType(XmlAccessType.FIELD)
    public static class Namespace {

        @XmlElement(name = "meta")
        private List<Meta> metas;

        public Namespace() {
        }

        public Namespace(List<Meta> list) {
            metas = list;
        }

        public List<Meta> getMetas() {
            return metas;
        }

    }

    @Override
    public Namespace marshal(Map<String, String> map) throws Exception {
        List<Meta> list = new ArrayList<>();
        for (Map.Entry<String, String> entry : map.entrySet()) {
            Meta meta = new Meta();
            meta.setProperty(entry.getKey());
            meta.setContent(entry.getValue());
            list.add(meta);
        }
        return new Namespace(list);
    }

    @Override
    public Map<String, String> unmarshal(Namespace metaList) throws Exception {
        Map<String, String> map = new HashMap<>();
        for (Meta meta : metaList.metas) {
            map.put(meta.getProperty(), meta.getContent());
        }
        return map;
    }

}

我在这里添加了另一个帮助类来描述Namespace

以上是关于如何使用Moxy将xml属性解析为键值的主要内容,如果未能解决你的问题,请参考以下文章

将 XML 字符串 API 响应转换为键值对象 C#

Spring Data Elasticsearch 动态映射。将属性映射为键值?

如何将 url 参数保留为键值

如何在php中将对象数组转换为键值对

Moxy Xpath ::“提升”属性

如何通过使用EclipseLink Moxy的注释来指定XML名称空间,schemaLocation和名称空间URI?