JAXB - Java / XMLValue和XMLElement冲突

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAXB - Java / XMLValue和XMLElement冲突相关的知识,希望对你有一定的参考价值。

我有下一个html,我要解析:

My input: 
<div>
    <span id="x1x1"> bla bla </span>
</div>
<span>
    <div> bla bla </div>
</span>

My output in java:
    jaxbContext = JAXBContext.newInstance(Div.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    jaxbUnmarshaller.unmarshal(file);
    System.out.println("id " + div1.getSpan().get(0).get(id) + "value " + div1.getSpan().get(0).get(id))
    // should print: id = x1x1 value = bla bla

我有下一堂课:

public class Span
    List<Div> div;

    public List<Div> getDiv() {
        return div;
    }

    @XmlElement
    public void setDiv(List<Div> div) {
        for (int i = 0 ; i<div.size(); i++){
            System.out.print("element")}
        this.div = div;
    }

和:

public class Div 
    List<Span> span = div1.get

    @XmlElement
    public void setSpan(List<Span> span) {
        for (int i = 0 ; i<span.size(); i++){
            System.out.print("element")}
        this.span = span;
    }

    public List<Button> getSpan() {
        return span;
    }

现在,我也想要跨度的值(“bla bla”)。所以我添加到类Span

String value;

public String getValue() {
    return value;
}

@XmlValue
public void setValue(String value) {
    this.value = value;
}

它给了我下一个错误:

 If a class has '@XmlElement' property, it cannot have '@XmlValue' property.

我尝试使用@XMLMixed,但没有成功。我会很高兴举例代码示例。谢谢。

答案

UPDATE

任何可以同时包含文本和元素的子注释的元素都被认为具有混合内容。在JAXB中,这对应于@XmlMixed注释。 @XmlMixed可以单独用于收集属性(请参阅ORIGINAL ANSWER)或与@XmlAnyElement@XmlElementRef@XmlElementRefs结合使用。如果元素可以是任何你使用@XmlAnyElement的东西,如果它是一个已知元素你将使用@XmlElementRef并且它使用@XmlElementRefs不止一个已知元素。

跨度

如果在同一个span元素中同时存在text和div元素,则可以通过使用@XmlElementRef@XmlMixed注释属性来执行以下操作。在@XmlElementRef批注中指定的元素名称必须直接对应于为目标类指定的根元素。

@XmlRootElement
public class Span {

    List<Object> items = new ArrayList<Object>();

    @XmlMixed
    @XmlElementRef(type=Div.class, name="div")
    public List<Object> getItems() {
        return items;
    }

    public void setItems(List<Object> mixed) {
        this.items = items;
    }


}

DIV

Div的元数据几乎与为Span指定的元数据相同。

@XmlRootElement
public class Div {

    List<Object> items = new ArrayList<Object>();

    @XmlElementRef(name="span", type=Span.class)
    @XmlMixed
    public List<Object> getItems() {
        return items;
    }

    public void setItems(List<Object> items) {
        this.items = items;
    }

}

演示

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Span span = (Span) unmarshaller.unmarshal(new StringReader("<span>Text<div>Text2</div>Text3</span>"));
        System.out.println(span.getItems());

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

}

产量

[Text, forum15495156.Div@289f6ae, Text3]
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<span>Text<div>Text2</div>Text3</span>

原始答案

你可以添加一个用List<String>注释的@XmlMixed属性到你的Span类:

跨度

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

@XmlRootElement
public class Span {
    List<Div> div;
    List<String> mixed;

    @XmlMixed
    public List<String> getMixed() {
        return mixed;
    }

    public void setMixed(List<String> mixed) {
        this.mixed = mixed;
    }

    public List<Div> getDiv() {
        return div;
    }

    @XmlElement
    public void setDiv(List<Div> div) {
        for (int i = 0; i < div.size(); i++) {
            System.out.print("element");
        }
        this.div = div;
    }
}

演示

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

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Span span1 = (Span) unmarshaller.unmarshal(new StringReader("<span>bla bla bla</span>"));
        System.out.println(span1.getMixed());

        Span span2 = (Span) unmarshaller.unmarshal(new StringReader("<span><div/><div/></span>"));
        System.out.println(span2.getDiv());
    }

}

产量

[bla bla bla]
elementelement[forum15495156.Div@1f80ce47, forum15495156.Div@4166a779]
另一答案

Creating Annotated JAXB Classes from Example XML Documents

通常,需要与JAXB绑定的XML文档没有内容的XSD,但是如果您有XSD,还有一些很好的工具可以自动完成这项工作。这是我用来快速填补这个空白并获得高质量绑定代码的过程。希望这有助于回答这个问题,并为此类问题提供一般解决方案。

高级流程

这是我用来为这个随机XML片段创建代码的过程:

  1. 获得一个高质量的例子。
  2. 使用名为Trang的工具从示例创建XSD。
  3. 从XSD生成绑定代码。

整个过程花了我不到5分钟,预装了工具,并产生高质量的结果。这是一个非常简单的示例,但示例XML文档的复杂性很容易上升,而不会增加处理时间或降低质量。

创建一个好的质量示例

示例文档是此过程中最重要的部分。对于更复杂的结构,您可能需要多个文档来捕获所需的信息,但我们将坚持使用单个文档案例。我们可以通过将提供的输入包装在<div/>中来创建一个示例来创建一个名为example.xml的文件:

<div>
  <div>
    <span id="x1x1"> bla bla </span>
  </div>
  <span>
    <div> bla bla </div>
  </span>
</div>

此示例演示了<div/>s和<span/>s可以相互嵌套并包含内容。

注意:此HTML片段无效,因为块级元素不能嵌套在内联元素中。 “现成”模式以及从中生成的代码可能会阻塞此输入。

从示例中创建XSD

这是这个过程中的伏都教步骤。手动创建XSD会带来很多工作和错误的可能性。如果没有自动化过程,您可能会放弃生成器的复杂性并手动编写注释。幸运的是,有一个名为Trang的工具将填补这一空白。

Trang可以做很多事情,但它擅长的一项任务是从XML文档生成XSD。对于简单的结构,它可以完全处理这一步骤。对于更复杂的输入,它可以帮助您完成大部分工作。

在这个载体上可以从Maven Central获得Trang:

<dependency>
  <groupId>com.thaiopensource</groupId>
  <artifactId>trang</artifactId>
  <version>20091111</version>
</dependency>

您可以使用以下命令下载和转换example.xml文档:

wget http://repo1.maven.org/maven2/com/thaiopensource/trang/20091111/trang-20091111.jar
java -jar trang-20091111.jar example.xml example.xsd

这会产生example.xsd

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">
  <xs:element name="div">
    <xs:complexType mixed="true">
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="div"/>
        <xs:element ref="span"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
  <xs:element name="span">
    <xs:complexType mixed="true">
      <xs:sequence>
        <xs:element minOccurs="0" maxOccurs="unbounded" ref="div"/>
      </xs:sequence>
      <xs:attribute name="id" type="xs:NCName"/>
    </xs:complexType>
  </xs:element>
</xs:schema>

对于简单文档,通常只需要它。对于更复杂的结构,您可能需要稍微编辑此文件,但至少您有一个可用的XSD作为起点。

从XSD生成绑定代码

现在我们有了一个XSD,我们可以利用XJC工具生成我们正在寻找的绑定代码。要运行XJC,请传递一个XSD,您要创建的包和一个src目录。这两个命令将在名为example.xsd的包中生成example的代码:

mkdir src
xjc -d src -p example example.xsd

现在,您将在src目录中拥有以下文件:

src/example/Div.java
src/example/ObjectFactory.java
src/example/Span.java

我已经在本文末尾包含了文件的内容,但这是我们感兴趣的文章,来自Span.java

@XmlElementRefs({
    @XmlElementRef(name = "div", type = Div.class),
    @XmlElementRef(name = "span", type = Span.class)
})
@XmlMixed
protected List<Object> content;

虽然手工编码注释可以工作,但自动创建这些文件可以节省时间并提高质量。它还允许您访问可用于XJC工具的所有插件。


由XJC生成的完整文件

例如/ Div.java:

//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a> 
// Any modifications to this file will be lost upon recompilation of the source schema. 
// Generated on: 2013.03.22 at 01:15:22 PM MST 
//


package example;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.Xm

以上是关于JAXB - Java / XMLValue和XMLElement冲突的主要内容,如果未能解决你的问题,请参考以下文章

java生成解析xml的另外两种方法JAXB

java生成解析xml的另外两种方法JAXB

JAXB2序列化XML

使用 JAXB 防止 XXE 攻击

JAXB - Annotations, Top-level Elements: XmlRootElement

XML编程总结——使用JAXB进行java对象和xml格式之间的相互转换