Java 如何解组包装在另一个元素中的元素

Java 如何解组包装在另一个元素中的元素,java,jaxb,Java,Jaxb,我想解组以下XML,并从中仅提取CD元素列表: <?xml version="1.0" encoding="UTF-8"?> <Root> <Header> <SomData> <Name>Name</Name> </SomData> </Header> <Message> <Dziuba

我想解组以下XML,并从中仅提取
CD
元素列表:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Header>
        <SomData>
            <Name>Name</Name>
        </SomData>
    </Header>
    <Message>
        <DziubasekInfo>
            <some_data>Data</some_data>
        </DziubasekInfo>
        <CATALOG>
            <Entry>
                <CD>
                    <TITLE>Empire Burlesque</TITLE>
                    <ARTIST>Bob Dylan</ARTIST>
                    <COUNTRY>USA</COUNTRY>
                    <COMPANY>Columbia</COMPANY>
                    <PRICE>10.90</PRICE>
                    <YEAR>1985</YEAR>
                </CD>
            </Entry>
            <Entry>
                <CD>
                    <TITLE>Hide your heart</TITLE>
                    <ARTIST>Bonnie Tyler</ARTIST>
                    <COUNTRY>UK</COUNTRY>
                    <COMPANY>CBS Records</COMPANY>
                    <PRICE>9.90</PRICE>
                    <YEAR>1988</YEAR>
                </CD>
            </Entry>
            <Entry>
                <CD>
                    <TITLE>Greatest Hits</TITLE>
                    <ARTIST>Dolly Parton</ARTIST>
                    <COUNTRY>USA</COUNTRY>
                    <COMPANY>RCA</COMPANY>
                    <PRICE>9.90</PRICE>
                    <YEAR>1982</YEAR>
                </CD>
            </Entry>
        </CATALOG>
    </Message>
</Root>


如您所见,这里有3个类:
Catalog
它包装
Entry
它反过来包装
Cd
class.
实际上,每个
条目
只包含一个
Cd
条目。

有没有办法消除这个包装类中的一个,只使用2个类而不是3个类
为了简化这段代码,特别是这段代码看起来有点笨拙:

e.getCdList().get(0).getArtist(), 
e.getCdList().get(0).getTitle(), 
e.getCdList().get(0).getPrice()
如果列表中只有一个条目,并且总是只得到一个条目,这有点愚蠢,最好这样做:

e.getCdList().getArtist(), e.getCdList().getTitle(), e.getCdList().getPrice()

任何与XML相关的映射的基本点都不是代码,而是XML(实际上是XML模式)。JAXB注释定义了模式。因此,如果您的XML具有模式 就像你所展示的:

<CATALOG>
        <Entry>
            <CD>
                <TITLE>Empire Burlesque</TITLE>
                <ARTIST>Bob Dylan</ARTIST>
                <COUNTRY>USA</COUNTRY>
                <COMPANY>Columbia</COMPANY>
                <PRICE>10.90</PRICE>
                <YEAR>1985</YEAR>
            </CD>
        </Entry>
        ...

皇帝讽刺剧
鲍勃·迪伦
美国
哥伦比亚
10.90
1985
...
那就是它的本来面目。Entry元素有CD元素。 如果要消除CD元素,则XML必须如下所示:

<CATALOG>
        <Entry>
                <TITLE>Empire Burlesque</TITLE>
                <ARTIST>Bob Dylan</ARTIST>
                <COUNTRY>USA</COUNTRY>
                <COMPANY>Columbia</COMPANY>
                <PRICE>10.90</PRICE>
                <YEAR>1985</YEAR>
        </Entry>

皇帝讽刺剧
鲍勃·迪伦
美国
哥伦比亚
10.90
1985
不多也不少。。。Java对象(带有JAXB注释)只是XML模式指示内容的反映。如果您不能更改XML,那么您必须接受它


顺便说一句:我很确定条目可能除了CD元素之外还有其他元素,比如DVD、磁带、VINIL等等。

任何与XML相关的映射的基本点不是代码,而是XML(实际上是XML模式)。JAXB注释定义了模式。因此,如果您的XML具有模式 就像你所展示的:

<CATALOG>
        <Entry>
            <CD>
                <TITLE>Empire Burlesque</TITLE>
                <ARTIST>Bob Dylan</ARTIST>
                <COUNTRY>USA</COUNTRY>
                <COMPANY>Columbia</COMPANY>
                <PRICE>10.90</PRICE>
                <YEAR>1985</YEAR>
            </CD>
        </Entry>
        ...

皇帝讽刺剧
鲍勃·迪伦
美国
哥伦比亚
10.90
1985
...
那就是它的本来面目。Entry元素有CD元素。 如果要消除CD元素,则XML必须如下所示:

<CATALOG>
        <Entry>
                <TITLE>Empire Burlesque</TITLE>
                <ARTIST>Bob Dylan</ARTIST>
                <COUNTRY>USA</COUNTRY>
                <COMPANY>Columbia</COMPANY>
                <PRICE>10.90</PRICE>
                <YEAR>1985</YEAR>
        </Entry>

皇帝讽刺剧
鲍勃·迪伦
美国
哥伦比亚
10.90
1985
不多也不少。。。Java对象(带有JAXB注释)只是XML模式指示内容的反映。如果您不能更改XML,那么您必须接受它


顺便说一句:我很确定条目可能有CD以外的元素,如DVD、磁带、VINIL等。

我最终用EclipseLink/Moxy和
@XmlPath(value=“Entry/CD”)
注释解决了这个问题。

Cd
类与问题中的相同。
这是
目录
类:

@XmlRootElement(name="CATALOG")
@XmlAccessorType(XmlAccessType.FIELD)
public class Catalog {

   @XmlElement(name = "CD", type = Cd.class)
   @XmlPath(value="Entry/CD")
   private List<Cd> list = new ArrayList<>();

    ... getters/setters

}

我最终用EclipseLink/Moxy和
@XmlPath(value=“Entry/CD”)
注释解决了这个问题
Cd
类与问题中的相同。
这是
目录
类:

@XmlRootElement(name="CATALOG")
@XmlAccessorType(XmlAccessType.FIELD)
public class Catalog {

   @XmlElement(name = "CD", type = Cd.class)
   @XmlPath(value="Entry/CD")
   private List<Cd> list = new ArrayList<>();

    ... getters/setters

}

非常感谢。最后我自己用
@XmlPath(value=“Entry/CD”)
注释解决了这个问题,请看下面我的答案。谢谢。我最终自己用
@XmlPath(value=“Entry/CD”)
注释解决了这个问题,请参见下面的答案。
@XmlRootElement(name="CATALOG")
@XmlAccessorType(XmlAccessType.FIELD)
public class Catalog {

   @XmlElement(name = "CD", type = Cd.class)
   @XmlPath(value="Entry/CD")
   private List<Cd> list = new ArrayList<>();

    ... getters/setters

}
System.setProperty("javax.xml.bind.context.factory","org.eclipse.persistence.jaxb.JAXBContextFactory");

        InputStream inp = getClass().getResourceAsStream("cd_catalog.xml");

        assertTrue(inp != null);

        XMLInputFactory xif = XMLInputFactory.newFactory();
        StreamSource source = new StreamSource(inp);

        XMLStreamReader xsr = xif.createXMLStreamReader(source);

        while (!(xsr.isStartElement() && "CATALOG".equals(xsr.getLocalName()))) {
            xsr.next();
        }

        JAXBContext jc = JAXBContext.newInstance(Catalog.class);
        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Catalog catalog = unmarshaller.unmarshal(xsr, Catalog.class).getValue();

        System.out.println("Entries = " + catalog.getList().size());

        for (Cd e : catalog.getList()) {
            System.out.format("CD: %20s / %30s / %10s\n", e.getArtist(), e.getTitle(), e.getPrice());
        }

        xsr.close();