简体   繁体   English

通过JAXB解组XML

[英]Unmarshal XML via JAXB

I have a xml as follows: 我有一个XML,如下所示:

<VisitorDataList>
  <VisitorData>
   <Attribute1List>
            <Attribute1>
                <Attribute1Name>name1</Attribute1Name>
                <Attribute1Id>2</Attribute1Id>
            </Attribute1>
            <Attribute1>
                <Attribute1Name>name1</Attribute1Name>
                <Attribute1Id>3</Attribute1Id>
            </Attribute1>
            <Attribute1>
                <Attribute1Name>name1</Attribute1Name>
                <Attribute1Id>1</Attribute1Id>
            </Attribute1>
        </Attribute1List>
     <Attribute2List>
            <Attribute2>
                <Attribute2Name>name2</Attribute2Name>
                <Attribute2Id>113</Attribute2Id>
            </Attribute2>
            <Attribute2>
                <Attribute2Name>name2</Attribute2Name>
                <Attribute2Id>115</Attribute2Id>
            </Attribute2>
            <Attribute2>
                <Attribute2Name>name2</Attribute2Name>
                <Attribute2Id>114</Attribute2Id>
            </Attribute2>
        </Attribute2List>
  </VisitorData>
 </VisitorDataList> 

The Attribute1List and Attribute2List is dynamic for both name and value, so they can be Attribute3List or Attribute4List and so on. Attribute1ListAttribute2List名称和值都是动态的,因此它们可以是Attribute3ListAttribute4List等。 Now i want to parse this xml via jAXB, the java bean is like: 现在,我想通过jAXB解析此xml,java bean类似于:

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

    @XmlElement(name = "VisitorData")
    public List<Visitor> getVisitors() {
        return visitors;
    }

    public void setVisitors(List<Visitor> visitors) {
        this.visitors = visitors;
    }

}

public class Visitor {

    private List<String> attributes= new ArrayList<String>();

        public List<String> getAttributes() {
        return attributes;
    }

    public void setAttributes(List<String> attributes) {
        this.attributes= attributes;
    }
}

My question is how to map all the attribute names into one list? 我的问题是如何将所有属性名称映射到一个列表中? Thanks in advance. 提前致谢。

You could use JAXB to unmarshal from StAX with a StreamReaderDelegate to strip off the number from the element names. 您可以使用JAXB通过StreamReaderDelegate从StAX解组,以从元素名称中剥离数字。 Your JAXB mappings will then be made to elements 然后将JAXB映射到元素

Below is a link to an article I wrote where I use this approach to do case insensitive unmarshalling: 以下是我写的文章的链接,在其中我使用这种方法进行不区分大小写的编组:


Java Model Java模型

VistorDataList VistorDataList

import java.util.List;

import javax.xml.bind.annotation.*;

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

    private List<Visitor> visitors;

    @XmlElementWrapper(name="VisitorData")
    @XmlElement(name = "AttributeList")
    public List<Visitor> getVisitors() {
        return visitors;
    }

    public void setVisitors(List<Visitor> visitors) {
        this.visitors = visitors;
    }

}

Visitor 游客

import java.util.*;
import javax.xml.bind.annotation.XmlElement;

public class Visitor {

    private List<String> attributes = new ArrayList<String>();

    @XmlElement(name="AttributeName")
    public List<String> getAttributes() {
        return attributes;
    }

    public void setAttributes(List<String> attributes) {
        this.attributes = attributes;
    }

}

Demo Code 示范代码

Demo 演示

import javax.xml.bind.*;
import javax.xml.stream.*;
import javax.xml.stream.util.StreamReaderDelegate;
import javax.xml.transform.stream.StreamSource;

public class Demo {

    public static void main(String[] args) throws Exception {
        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource xml = new StreamSource("src/forum18071557/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(xml);

        xsr = new StreamReaderDelegate(xsr) {

            @Override
            public String getLocalName() {
                String localName = super.getLocalName();
                if(localName.startsWith("Attribute") && localName.endsWith("List")) {
                    return "AttributeList";
                } else if(localName.startsWith("Attribute") && localName.endsWith("Name")) {
                    return "AttributeName";
                } else if(localName.startsWith("Attribute")) {
                    return "ignore";
                } else {
                    return localName;
                }
            }

        };

        xsr = xif.createFilteredReader(xsr, new StreamFilter() {
            @Override
            public boolean accept(XMLStreamReader reader) {
                if(reader.isStartElement() || reader.isEndElement()) {
                    return !reader.getLocalName().equals("ignore");
                } else {
                    return true;
                }
            }

        });

        JAXBContext jc = JAXBContext.newInstance(VisitorDataList.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        VisitorDataList vdl = (VisitorDataList) unmarshaller.unmarshal(xsr);

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(vdl, System.out);
    }

}

Output 产量

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VisitorDataList>
    <VisitorData>
        <AttributeList>
            <AttributeName>name1</AttributeName>
            <AttributeName>name1</AttributeName>
            <AttributeName>name1</AttributeName>
        </AttributeList>
        <AttributeList>
            <AttributeName>name2</AttributeName>
            <AttributeName>name2</AttributeName>
            <AttributeName>name2</AttributeName>
        </AttributeList>
    </VisitorData>
</VisitorDataList>

I tried your XML file to unmarshal using JAXB but I was only able to parse it statically.You can try it once. 我尝试使用JAXB解封XML文件,但只能静态解析它。您可以尝试一次。

visitor.xml visitor.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<VisitorDataList>
  <VisitorData>
   <AttributeList>
            <Attribute>
                <AttributeName>name1</AttributeName>
                <AttributeId>2</AttributeId>
            </Attribute>
            <Attribute>
                <AttributeName>name1</AttributeName>
                <AttributeId>3</AttributeId>
            </Attribute>
            <Attribute>
                <AttributeName>name1</AttributeName>
                <AttributeId>1</AttributeId>
            </Attribute>
        </AttributeList>
     <AttributeList>
            <Attribute>
                <AttributeName>name2</AttributeName>
                <AttributeId>113</AttributeId>
            </Attribute>
            <Attribute>
                <AttributeName>name2</AttributeName>
                <AttributeId>115</AttributeId>
            </Attribute>
                <Attribute>
                <AttributeName>name2</AttributeName>
                <AttributeId>114</AttributeId>
            </Attribute> 
        </AttributeList>
  </VisitorData>

visitordatalist.java visitordatalist.java

package foo.bar.me.too;

import java.util.List;

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

@XmlRootElement(name="VisitorDataList")
public class visitordatalist {


    List<visitordata> vstd;



    @XmlElement(name="VisitorData")
    public List<visitordata> getVstd() {
        return vstd;
    }

    public void setVstd(List<visitordata> vstd) {
        this.vstd = vstd;
    }



}

visitordata.java visitordata.java

package foo.bar.me.too;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;

public class visitordata {

    List<attributelist> atrl;


    public String toString() {
        return atrl.toString();
    }

    @XmlElement(name="AttributeList")
     public List<attributelist> getAtrl() {
        return atrl;
    }
    public void setAtrl(List<attributelist> atrl) {
        this.atrl = atrl;
    }


}

attributelist.java attributelist.java

package foo.bar.me.too;

import java.util.List;

import javax.xml.bind.annotation.XmlElement;

public class attributelist {

    List<attribute> atr;
     public String toString() {
            return atr.toString();
        }

     @XmlElement(name="Attribute")
    public List<attribute> getAtr() {
        return atr;
    }

    public void setAtr(List<attribute> atr) {
        this.atr = atr;
    }

    }

attribute.java attribute.java

package foo.bar.me.too;

import javax.xml.bind.annotation.XmlElement;

public class attribute {

    String atrName;
    String atrId;

     public String toString() {
            return atrName+"   "+atrId;

        }


    @XmlElement(name="AttributeName")
    public String getAtrName() {
        return atrName;
    }
    public void setAtrName(String atrName) {
        this.atrName = atrName;
    }

    @XmlElement(name="AttributeId")
    public String getAtrId() {
        return atrId;
    }
    public void setAtrId(String atrId) {
        this.atrId = atrId;
    }


 }      

JAXBExample.java JAXBExample.java

package foo.bar.me.too;

import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;

public class JAXBExample {
    public static void main(String[] args) {

     try {

        File file = new File("visitor.xml");
        JAXBContext jaxbContext = JAXBContext.newInstance(visitordatalist.class);

        Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
        visitordatalist  vstdl = (visitordatalist) jaxbUnmarshaller.unmarshal(file);

        System.out.println(vstdl.getVstd());

      } catch (JAXBException e) {
        e.printStackTrace();
      }

    }

}

There is a special arcane knowledge for some special JAXB implementations. 对于某些特殊的JAXB实现,有一种特殊的奥术知识。 For example, for FasterXML (used in WildFly) you should change one property to make it work (just override an additional method in Delegator): 例如,对于FasterXML(在WildFly中使用),您应该更改一个属性以使其起作用(只需重写Delegator中的其他方法):

@Override
public Object getProperty(String name) {
    Object property = super.getProperty(name);
    if("org.codehaus.stax2.internNames".equals(name)) {
        return Boolean.FALSE;
    }
    return property;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM