1

这个 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>
4

2 回答 2

4

下面是如何使用 JAXB 和 StAX 的组合来支持这个用例。

演示代码

演示

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

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

}

输入.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 模型。

框架

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;

}
于 2013-08-07T10:17:37.790 回答
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);
            }
        }
    }
于 2013-08-07T07:03:39.300 回答