读取具有不同名称但属于同一类型的元素列表

时间:2012-11-04 15:12:33

标签: java xml jaxb

我试图将JAXB注释添加到类中以便解组与此类似的XML(注意我不需要将java bean编组为XML ...):

    <fixture_statistics id="3812596">
      <home_team_stats id="2">
        <id>2</id>
        <tackles>58</tackles>
        <possession>1868</possession>
        <territory>2603</territory>
        <minutes_in_22>1316</minutes_in_22>
        ...
      </home_team_stats>
      <guest_team_stats id="21061">
        <id>21061</id>
        <tackles>20</tackles>
        <possession>3114</possession>
        <territory>2379</territory>
        <minutes_in_22>1171</minutes_in_22>
        ...
      </guest_team_stats>
      <home_player_1 id="2306143" teamid="2">
        <id>2306143</id>
        <tackles>3</tackles>
        <metres_gained>38</metres_gained>
        ...
      </home_player_1>
      <home_player_1 id="2306143" teamid="2">
        <id>2306143</id>
        <tackles>3</tackles>
        <metres_gained>38</metres_gained>
        ...
      </home_player_1>
      <home_player_1 id="2306143" teamid="2">
        <id>2306143</id>
        <tackles>3</tackles>
        <metres_gained>38</metres_gained>
        ...
      </home_player_1>
      ...
      <guest_player_1 id="2306143" teamid="2">
        <id>2306143</id>
        <tackles>3</tackles>
        <metres_gained>38</metres_gained>
        ...
      </guest_player_1>
      <guest_player_2 id="2306143" teamid="2">
        <id>2306143</id>
        <tackles>3</tackles>
        <metres_gained>38</metres_gained>
        ...
      </guest_player_2>
      <guest_player_3 id="2306143" teamid="2">
        <id>2306143</id>
        <tackles>3</tackles>
        <metres_gained>38</metres_gained>
        ...
      </guest_player_3>
      ...
</fixture_statistics>

*注意在我为此问题复制和粘贴时忽略了一些元素值...

我已设法映射&#34; fixture_statistics&#34;,&#34; home_team_stats&#34;和&#34; guest_team_stats&#34;它们各自的类的元素,我能够正确地解组这些元素,但我遇到的问题是&#34; home_player_n&#34;和#34; guest_player_n&#34;元素。我创建了一个包含在这些元素中找到的属性的类,但我不知道如何处理元素具有不同名称的事实 - &#34; home_player_1&#34;直到&#34; home_player_22&#34;和客人一样。

以下是我的夹具统计类的示例,以及我的夹具播放器统计类,以便有人可以指出我出错的地方......

@XmlRootElement(name = "fixture_statistics")
@XmlAccessorType(XmlAccessType.FIELD)
public class FixtureStatistics {

    private Collection<FixturePlayerStatistics> homeTeamPlayerStatistics = new ArrayList<>();

    private Collection<FixturePlayerStatistics> guestTeamPlayerStatistics = new ArrayList<>();
}

@XmlAccessorType(XmlAccessType.FIELD)
public class FixturePlayerStatistics {
    @XmlElement(name="id")
    private Long playerId;
    private Integer tackles;
    @XmlElement(name="metres_gained")
    private Integer metresGained;
}

在FixturePlayerStatistics类中,我无法添加XMlRootElement注释,因为该元素可能是44个字符串中的1个,我也暂时从FixtureStatistics类中的集合中删除了任何注释,因为我老实说不清楚是什么去那里。我已经尝试使用@XmlElementRef,指定所有可能的元素名称,但这对我来说还不起作用,XML也无法更改,我没有可以使用的模式,只有来自API的结果XML调用

1 个答案:

答案 0 :(得分:2)

支持此用例有一些不同的选项。但总的来说,我建议避免将索引用于元素名称的情况。

选项#1 - 单独的字段/属性

处理此用例的一种方法是为22位客人和22位家庭玩家中的每一位拥有单独的字段/属性。

package forum13219778;

import javax.xml.bind.annotation.*;

@XmlRootElement(name = "fixture_statistics")
@XmlAccessorType(XmlAccessType.FIELD)
public class FixtureStatistics {

    FixturePlayerStatistics guest_player_1;
    FixturePlayerStatistics guest_player_2;
    FixturePlayerStatistics guest_player_3;
    ...
    FixturePlayerStatistics guest_player_22;

    FixturePlayerStatistics home_player_1;
    FixturePlayerStatistics home_player_2;
    FixturePlayerStatistics home_player_3;
    ...
    FixturePlayerStatistics home_player_22;     
}

选项#2 - 使用SAX XMLFilter到STRIP OFF _#SUFFIX

如果您的用例仅涉及解组,那么您可以使用SAX XMLFilter去除每个元素上的唯一后缀,并且在JAXB注释中只需映射到home_playerguest_player 。有关XMLFilter示例,请参阅:


选项#3 - 使用@XmlElementRefsObjectFactory

<强> FixtureStatistics

要使用@XmlElementRefs / @XmlElementRef注释,您需要更改集合以容纳JAXBElement<FixturePlayerStatistics>的实例。 JAXBElement将用于保存元素名称信息。

package forum13219778;

import java.util.*;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement(name = "fixture_statistics")
@XmlAccessorType(XmlAccessType.FIELD)
public class FixtureStatistics {

    @XmlElementRefs({ 
        @XmlElementRef(name="home_player_1"),
        @XmlElementRef(name="home_player_2"),
        @XmlElementRef(name="home_player_3")
    })
    private Collection<JAXBElement<FixturePlayerStatistics>> homeTeamPlayerStatistics = new ArrayList<>();

    @XmlElementRefs({ 
        @XmlElementRef(name="guest_player_1"),
        @XmlElementRef(name="guest_player_2"),
        @XmlElementRef(name="guest_player_3")
    })
    private Collection<JAXBElement<FixturePlayerStatistics>> guestTeamPlayerStatistics = new ArrayList<>();

}

<强> 的ObjectFactory

@XmlElementRef结合使用时,您需要使用@XmlElementDecl注释声明根元素。这是通过使用@XmlRegistry注释的对象工厂类完成的。

package forum13219778;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name = "home_player_1")
    public JAXBElement<FixturePlayerStatistics> createHomePlayer1(FixturePlayerStatistics player) {
        return new JAXBElement<FixturePlayerStatistics>(new QName("home_player_1"), FixturePlayerStatistics.class, player);
    }

    @XmlElementDecl(name = "home_player_2")
    public JAXBElement<FixturePlayerStatistics> createHomePlayer2(FixturePlayerStatistics player) {
        return new JAXBElement<FixturePlayerStatistics>(new QName("home_player_2"), FixturePlayerStatistics.class, player);
    }

    @XmlElementDecl(name = "home_player_3")
    public JAXBElement<FixturePlayerStatistics> createHomePlayer3(FixturePlayerStatistics player) {
        return new JAXBElement<FixturePlayerStatistics>(new QName("home_player_3"), FixturePlayerStatistics.class, player);
    }

    @XmlElementDecl(name = "guest_player_1")
    public JAXBElement<FixturePlayerStatistics> createGuestPlayer1(FixturePlayerStatistics player) {
        return new JAXBElement<FixturePlayerStatistics>(new QName("guest_player_1"), FixturePlayerStatistics.class, player);
    }


    @XmlElementDecl(name = "guest_player_2")
    public JAXBElement<FixturePlayerStatistics> createGuestPlayer2(FixturePlayerStatistics player) {
        return new JAXBElement<FixturePlayerStatistics>(new QName("guest_player_2"), FixturePlayerStatistics.class, player);
    }

    @XmlElementDecl(name = "guest_player_3")
    public JAXBElement<FixturePlayerStatistics> createGuestPlayer3(FixturePlayerStatistics player) {
        return new JAXBElement<FixturePlayerStatistics>(new QName("guest_player_3"), FixturePlayerStatistics.class, player);
    }

}

<强> 演示

package forum13219778;

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(FixtureStatistics.class, ObjectFactory.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum13219778/input.xml");
        FixtureStatistics fs = (FixtureStatistics) unmarshaller.unmarshal(xml);

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

}