如何使用JAXB注释将此XML转换为Java对象?

时间:2013-08-07 06:43:49

标签: java xml jaxb

这个XML设计非常痛苦,但无论如何都需要处理。 我不能把它作为<ack>个对象的列表,因为每个对象都有一组不同的标签,对吧? 请帮忙!

<frm>
   <version>1.1.0</version>
   <ack>
      <id_1>--</id_1>
      <pow_1 />
      <temp_1 />
      <state_1>fixed</state_1>
   </ack>
   <ack>
      <id_2>0000C6F5</id_2>
      <pow_2>0w</pow_2>
      <temp_2>---</temp_2>
      <state_2>fixed</state_2>
   </ack>
   <ack>
      <id_3>--</id_3>
      <pow_3 />
      <temp_3 />
      <state_3>fixed</state_3>
   </ack>
   <ack>
      <id_4>--</id_4>
      <pow_4 />
      <temp_4 />
      <state_4>fixed</state_4>
   </ack>
   <ack>
      <id_5>--</id_5>
      <pow_5 />
      <temp_5 />
      <state_5>fixed</state_5>
   </ack>
   <ack>
      <id_6>--</id_6>
      <pow_6 />
      <temp_6 />
      <state_6>fixed</state_6>
   </ack>
   <ack>
      <id_7>--</id_7>
      <pow_7 />
      <temp_7 />
      <state_7>fixed</state_7>
   </ack>
   <ack>
      <id_8>--</id_8>
      <pow_8 />
      <temp_8 />
      <state_8>fixed</state_8>
   </ack>
   <ack>
      <id_9>--</id_9>
      <pow_9 />
      <temp_9 />
      <state_9>fixed</state_9>
   </ack>
   <ack>
      <id_10>--</id_10>
      <pow_10 />
      <temp_10 />
      <state_10>fixed</state_10>
   </ack>
</frm>

2 个答案:

答案 0 :(得分:4)

以下是使用JAXB和StAX组合支持此用例的方法。

演示代码

<强>演示

我们可以使用StreamReaderDelegate来更改元素名称的报告方式。我们将使用它删除_及其后的所有内容。

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 {
        JAXBContext jc = JAXBContext.newInstance(Frm.class);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource source = new StreamSource("src/forum18096385/input.xml");
        XMLStreamReader xsr = xif.createXMLStreamReader(source);
        xsr = new StreamReaderDelegate(xsr) {

            @Override
            public String getLocalName() {
                String localName = super.getLocalName();
                int underScoreIndex = localName.indexOf('_');
                if(underScoreIndex >= 0) {
                    return localName.substring(0, underScoreIndex);
                }
                return localName;
            }

        };

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Frm frm = (Frm) unmarshaller.unmarshal(xsr);

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

}

<强> input.xml中

您问题中的XML。

<强>输出

由于我们将映射到修改后的XML,如果我们编组结果,它将看起来与输入不同。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<frm>
    <version>1.1.0</version>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>0000C6F5</id>
        <pow>0w</pow>
        <temp>---</temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
    <ack>
        <id>--</id>
        <pow></pow>
        <temp></temp>
        <state>fixed</state>
    </ack>
</frm>

Java模型

以下是我们将映射到修改后的XML的Java模型。

<强> FRM

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

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Frm {

    private String version;
    private List<Ack> ack;

}

<强>确认

import javax.xml.bind.annotation.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Ack {

    private String id;
    private String pow;
    private String temp;
    private String state;

}

答案 1 :(得分:0)

我认为使用StAX会更简单

    XMLStreamReader xr = ...
    while (xr.hasNext()) {
        int n = xr.next();
        if (n == XMLStreamReader.START_ELEMENT)) {
            String name = xr.getLocalName();
            if (name.startsWith("id")) {
                ack = new Ack();
                ack.id = xr.getElementText();
            } else if (name.startsWith("pow")) {
                ...
            } else if (name.startsWith("state")) {
                ack.state = xr.getElementText();
                list.add(ack);
            }
        }
    }