JAXB – Java / XMLValue和XMLElement冲突

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

My input: 
bla bla
bla bla
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; public List
getDiv() { return div; } @XmlElement public void setDiv(List
div) { for (int i = 0 ; i<div.size(); i++){ System.out.print("element")} this.div = div; }

和:

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

现在,我也想要跨度的值(“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@XmlAnyElement@XmlElementRefs结合使用。 如果元素可以是任何您使用@XmlAnyElement的元素,如果它是一个已知元素,您将使用@XmlElementRef并且您使用@XmlElementRef是多个已知元素。

跨度

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

 @XmlRootElement public class Span { List items = new ArrayList(); @XmlMixed @XmlElementRef(type=Div.class, name="div") public List getItems() { return items; } public void setItems(List mixed) { this.items = items; } } 

DIV

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

 @XmlRootElement public class Div { List items = new ArrayList(); @XmlElementRef(name="span", type=Span.class) @XmlMixed public List getItems() { return items; } public void setItems(List 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("Text
Text2
Text3
")); 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]  Text
Text2
Text3

原始答案

您可以将带有@XmlMixed注释的List属性添加到Span类:

跨度

 import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement public class Span { List
div; List mixed; @XmlMixed public List getMixed() { return mixed; } public void setMixed(List mixed) { this.mixed = mixed; } public List
getDiv() { return div; } @XmlElement public void setDiv(List
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("bla bla bla")); System.out.println(span1.getMixed()); Span span2 = (Span) unmarshaller.unmarshal(new StringReader("
")); System.out.println(span2.getDiv()); } }

产量

 [bla bla bla] elementelement[forum15495156.Div@1f80ce47, forum15495156.Div@4166a779] 

从示例XML文档创建带注释的JAXB类

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

高级流程

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

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

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

创建一个好的质量示例

示例文档是此过程中最重要的部分。 对于更复杂的结构,您可能需要多个文档来捕获所需的信息,但我们将坚持使用单个文档案例。 我们可以通过将提供的输入包装在

中来创建一个名为example.xml的文件来解决问题:

 
bla bla
bla bla

此示例演示

s和 s可以相互嵌套并包含内容。

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

从示例创建XSD

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

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

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

  com.thaiopensource trang 20091111  

您可以使用以下命令下载和转换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

                    

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

从XSD生成绑定代码

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

 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 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 http://java.sun.com/xml/jaxb // 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.XmlAccessorType; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlElementRefs; import javax.xml.bind.annotation.XmlMixed; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; /** * 

Java class for anonymous complex type. * *

The following schema fragment specifies the expected content contained within this class. * *

 * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <choice maxOccurs="unbounded" minOccurs="0"> * <element ref="{}div"/> * <element ref="{}span"/> * </choice> * </restriction> * </complexContent> * </complexType> * 

* * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "content" }) @XmlRootElement(name = "div") public class Div { @XmlElementRefs({ @XmlElementRef(name = "div", type = Div.class), @XmlElementRef(name = "span", type = Span.class) }) @XmlMixed protected Listcontent; /** * Gets the value of the content property. * *

* This accessor method returns a reference to the live list, * not a snapshot. Therefore any modification you make to the * returned list will be present inside the JAXB object. * This is why there is not a set method for the content property. * *

* For example, to add a new item, do as follows: *

 * getContent().add(newItem); * 

* * *

* Objects of the following type(s) are allowed in the list * {@link Div } * {@link String } * {@link Span } * * */ public ListgetContent() { if (content == null) { content = new ArrayList(); } return this.content; } }

例如/ Span.java

 // // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 // See http://java.sun.com/xml/jaxb // 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.XmlAccessorType; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlMixed; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlSchemaType; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.CollapsedStringAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; /** * 

Java class for anonymous complex type. * *

The following schema fragment specifies the expected content contained within this class. * *

 * <complexType> * <complexContent> * <restriction base="{http://www.w3.org/2001/XMLSchema}anyType"> * <sequence> * <element ref="{}div" maxOccurs="unbounded" minOccurs="0"/> * </sequence> * <attribute name="id" type="{http://www.w3.org/2001/XMLSchema}NCName" /> * </restriction> * </complexContent> * </complexType> * 

* * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "content" }) @XmlRootElement(name = "span") public class Span { @XmlElementRef(name = "div", type = Div.class) @XmlMixed protected Listcontent; @XmlAttribute @XmlJavaTypeAdapter(CollapsedStringAdapter.class) @XmlSchemaType(name = "NCName") protected String id; /** * Gets the value of the content property. * *

* This accessor method returns a reference to the live list, * not a snapshot. Therefore any modification you make to the * returned list will be present inside the JAXB object. * This is why there is not a set method for the content property. * *

* For example, to add a new item, do as follows: *

 * getContent().add(newItem); * 

* * *

* Objects of the following type(s) are allowed in the list * {@link Div } * {@link String } * * */ public ListgetContent() { if (content == null) { content = new ArrayList(); } return this.content; } /** * Gets the value of the id property. * * @return * possible object is * {@link String } * */ public String getId() { return id; } /** * Sets the value of the id property. * * @param value * allowed object is * {@link String } * */ public void setId(String value) { this.id = value; } }

例如/ ObjectFactory.java

 // // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 // See http://java.sun.com/xml/jaxb // 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 javax.xml.bind.annotation.XmlRegistry; /** * This object contains factory methods for each * Java content interface and Java element interface * generated in the example package. * 

An ObjectFactory allows you to programatically * construct new instances of the Java representation * for XML content. The Java representation of XML * content can consist of schema derived interfaces * and classes representing the binding of schema * type definitions, element declarations and model * groups. Factory methods for each of these are * provided in this class. * */ @XmlRegistry public class ObjectFactory { /** * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: example * */ public ObjectFactory() { } /** * Create an instance of {@link Div } * */ public Div createDiv() { return new Div(); } /** * Create an instance of {@link Span } * */ public Span createSpan() { return new Span(); } }