【问题标题】:JAVA - Marshalling/Unmarshalling XML - duplicate element getting created during marshallingJAVA - 编组/解组 XML - 在编组期间创建重复元素
【发布时间】:2018-08-05 00:47:28
【问题描述】:

我试图编组和解组 XML。为简单起见,我将删除命名空间的所有注释。

下面是我最终要寻找的 XML 的结构:

<?xml version="1.0" encoding="utf-16"?>
<RootElement>
  <Parent1>
    <Parent1Child1>
      <Parent1Child1Child1>v1</Parent1Child1Child1>
      <Parent1Child1Child2>v2</Parent1Child1Child2>
      <Parent1Child1Child3>v3</Parent1Child1Child3>
    </Parent1Child1>
    <Parent1Child2>v4</Parent1Child2>
  </Parent1>
</RootElement>

我的 RootElement 类如下:

package com.mysoftkey.jaxb;

import javax.xml.bind.annotation.XmlRootElement;

import java.util.ArrayList;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;

//@XmlRootElement(name="RootElement",namespace="http://yyyy")
@XmlRootElement(name="RootElement")
public class RootElement {
    //@XmlElementWrapper(name="Parent1",namespace="http://hhhh")
    @XmlElementWrapper(name="Parent1")
    @XmlElement(name="Parent1Child1")
    private ArrayList<Parent1Child1> p1;

    private String Parent1Child2;

    public void setparent1child1(ArrayList<Parent1Child1> Parent1) {
        this.p1=Parent1;
    }

    public ArrayList<Parent1Child1> getparent1child1(){
        return p1;
    }

    public String getparent1child2() {
        return Parent1Child2;
    }

    public void setparent1child2(String Parent1Child2) {
        this.Parent1Child2=Parent1Child2;
    }

    public void addparent1child1(Parent1Child1 Parent1Child1) {
        try {
                if (p1==null) {
                    p1=new ArrayList<Parent1Child1>();
                }
                p1.add(Parent1Child1);
        }catch (Exception e) {

        }
    }
}

我的“Parent1Child1”类如下:

package com.mysoftkey.jaxb;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="Parent1Child1")
public class Parent1Child1 {

    private String Parent1Child1Child1;
    private String Parent1Child1Child2;
    private String Parent1Child1Child3;

    public String getparent1child1child1() {
        return Parent1Child1Child1;
    }

    public void setparent1child1child1(String Parent1Child1Child1) {
        this.Parent1Child1Child1=Parent1Child1Child1;
    }

    public String getparent1child1child2() {
        return Parent1Child1Child2;
    }

    public void setparent1child1child2(String Parent1Child1Child2) {
        this.Parent1Child1Child2=Parent1Child1Child2;
    }

    public String getparent1child1child3() {
        return Parent1Child1Child3;
    }

    public void setparent1child1child3(String Parent1Child1Child3) {
        this.Parent1Child1Child3=Parent1Child1Child3;
    }
}

我有如下编组/解组的主要类:

package com.mysoftkey.jaxb;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;

public class ParseXML1 {

    public static String xml_filepath="C:\\...\\Testxml2.xml";

    public static void main(String[] args) throws JAXBException, FileNotFoundException {
        // TODO Auto-generated method stub

        //Create Parent1Child1 object and populate some values
        Parent1Child1 pcd1=new Parent1Child1();

        pcd1.setparent1child1child1("value1");
        pcd1.setparent1child1child2("value2");
        pcd1.setparent1child1child3("value3");

        RootElement rt1=new RootElement();
        rt1.addparent1child1(pcd1);
        rt1.setparent1child2("value4");

        //Initiate marshaller class
        JAXBContext cont=JAXBContext.newInstance(RootElement.class);
        Marshaller m=cont.createMarshaller();

        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        m.marshal(rt1, System.out);
        m.marshal(rt1, new File("C:\\...\\Testxml3.xml"));

        //Create JAXB context and initiate unmarshaller



        Unmarshaller um=cont.createUnmarshaller();

        RootElement root1=(RootElement)um.unmarshal(new FileReader("C:\\...\\Testxml3.xml"));
        ArrayList<Parent1Child1> pc1=root1.getparent1child1();
        //System.out.println(pc1.size());
        for (Parent1Child1 p:pc1)
        {
            System.out.println(p.getparent1child1child1());
            System.out.println(p.getparent1child1child2());
            System.out.println(p.getparent1child1child3());
        }
        System.out.println(root1.getparent1child2());
    }

}

当我执行上述操作时,我得到以下内容:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RootElement>
    <Parent1>
        <Parent1Child1>
            <parent1child1child1>value1</parent1child1child1>
            <parent1child1child2>value2</parent1child1child2>
            <parent1child1child3>value3</parent1child1child3>
        </Parent1Child1>
    </Parent1>
    <parent1child1>
        <parent1child1child1>value1</parent1child1child1>
        <parent1child1child2>value2</parent1child1child2>
        <parent1child1child3>value3</parent1child1child3>
    </parent1child1>
    <parent1child2>value4</parent1child2>
</RootElement>
value1
value2
value3
value4

谁能告诉我为什么'Parent1Child1'标签被重复两次。一次进入 'Parent1' 包装器,然后再次在它之外。

如果我评论“RootElement”类的以下部分,我只会得到一次“parent1child1”标签。我不应该将“parent1child1”注释为 XMLElement 吗?请帮助理解。

@XmlElementWrapper(name="Parent1")
@XmlElement(name="parent1child1")

在 'RootElement' 类中注释上述行后的输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<RootElement>
    <parent1child1>
        <parent1child1child1>value1</parent1child1child1>
        <parent1child1child2>value2</parent1child1child2>
        <parent1child1child3>value3</parent1child1child3>
    </parent1child1>
    <parent1child2>value4</parent1child2>
</RootElement>
value1
value2
value3
value4

谢谢

【问题讨论】:

  • 尝试协调字段和 getter/setter 名称。
  • @lexicore,对不起,我不确定我是否完全明白了。你能详细说明你所说的协调是什么意思吗?您的意思是 xml 字段和 getter/setter 名称应该相同吗?
  • 类中的字段名称、getter 和 setter 似乎不遵循通常的约定。比如p1 vs. setparent1child1 vs. getparent1child1。我不确定这是不是原因,但这可能会使 JAXB 认为这是两个不同的属性,因此它们被编组两次——一次通过字段(考虑字段上的注释),一次通过属性(无注释 - 默认编组)。
  • @lexicore。非常感谢您的解释和指导。

标签: xml xml-parsing jaxb


【解决方案1】:

@lexicore 是对的。注意&lt;Parent1Child1&gt;(在 Parent1 包装器内)和&lt;parent1child1&gt;&lt;parent1child1&gt; 是从您的 getter/setter 生成的。

在对代码进行最少更改的同时获得所需 xml 的一种简单方法是使用 @XmlAccessorType(XmlAccessType.FIELD) 注释您的 RootElement 类。使用它,getter/setter 对仅在它们被某些 JAXB 注释显式注释时才绑定到 XML。

所以你的 RootElement 类看起来像这样:

@XmlRootElement(name="RootElement")
@XmlAccessorType(XmlAccessType.FIELD)
public class RootElement {
    //@XmlElementWrapper(name="Parent1",namespace="http://hhhh")
    @XmlElementWrapper(name="Parent1")
    @XmlElement(name="Parent1Child1")
    private ArrayList<Parent1Child1> p1;

    private String Parent1Child2;

    public void setparent1child1(ArrayList<Parent1Child1> Parent1) {
        this.p1=Parent1;
    }

    public ArrayList<Parent1Child1> getparent1child1(){
        return p1;
    }

    public String getparent1child2() {
        return Parent1Child2;
    }

    public void setparent1child2(String Parent1Child2) {
        this.Parent1Child2=Parent1Child2;
    }

    public void addparent1child1(Parent1Child1 Parent1Child1) {
        try {
            if (p1==null) {
                p1=new ArrayList<Parent1Child1>();
            }
            p1.add(Parent1Child1);
        }catch (Exception e) {

        }
    }
}

我试过了,效果很好。将 getter/setter 更改为通常的约定我认为仍然行不通,因为您的 &lt;Parent1Child1&gt; 以大写“P”开头(还没有尝试过)。

【讨论】:

    猜你喜欢
    • 2023-04-06
    • 2011-06-07
    • 1970-01-01
    • 1970-01-01
    • 2021-07-23
    • 2022-11-15
    • 1970-01-01
    • 2011-11-28
    • 1970-01-01
    相关资源
    最近更新 更多