JAXB - Java / XMLValue& XMLElement冲突

时间:2013-03-19 09:01:56

标签: java jaxb

我有下一个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;
    }

现在,我也想要跨度的值(&#34; bla bla&#34;)。所以我添加到课程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,但没有成功。我会很高兴举例代码示例。感谢。

2 个答案:

答案 0 :(得分:8)

<强>更新

任何可以同时包含文本和元素的子注释的元素都被认为具有混合内容。在JAXB中,这对应于@XmlMixed注释。 @XmlMixed可以单独用于集合属性(请参阅原始答案),也可以与@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的元数据几乎与为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的{​​{1}}属性添加到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]

答案 1 :(得分:3)

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

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

高级别流程

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

  1. 获得一个高质量的例子。
  2. 使用名为Trang的工具
  3. 从示例中创建XSD
  4. 从XSD生成绑定代码。
  5. 整个过程花了我不到5分钟,预先安装了工具,并产生高质量的结果。这是一个非常简单的示例,但示例XML文档的复杂性很容易上升,而不会增加处理时间或降低质量。

    创建优质示例

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

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

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

      

    注意:此HTML片段无效,因为块级元素不能嵌套在内联元素中。一个&#34;现成的&#34;架构以及从中生成的代码可能会阻塞此输入。

    从示例

    创建XSD

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

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

    Trang可以从Maven Central处获得此载体:

    <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.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;
    
    
    /**
     * <p>Java class for anonymous complex type.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * 
     * <pre>
     * &lt;complexType>
     *   &lt;complexContent>
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       &lt;choice maxOccurs="unbounded" minOccurs="0">
     *         &lt;element ref="{}div"/>
     *         &lt;element ref="{}span"/>
     *       &lt;/choice>
     *     &lt;/restriction>
     *   &lt;/complexContent>
     * &lt;/complexType>
     * </pre>
     * 
     * 
     */
    @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 List<Object> content;
    
        /**
         * Gets the value of the content property.
         * 
         * <p>
         * 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 <CODE>set</CODE> method for the content property.
         * 
         * <p>
         * For example, to add a new item, do as follows:
         * <pre>
         *    getContent().add(newItem);
         * </pre>
         * 
         * 
         * <p>
         * Objects of the following type(s) are allowed in the list
         * {@link Div }
         * {@link String }
         * {@link Span }
         * 
         * 
         */
        public List<Object> getContent() {
            if (content == null) {
                content = new ArrayList<Object>();
            }
            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 <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.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;
    
    
    /**
     * <p>Java class for anonymous complex type.
     * 
     * <p>The following schema fragment specifies the expected content contained within this class.
     * 
     * <pre>
     * &lt;complexType>
     *   &lt;complexContent>
     *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
     *       &lt;sequence>
     *         &lt;element ref="{}div" maxOccurs="unbounded" minOccurs="0"/>
     *       &lt;/sequence>
     *       &lt;attribute name="id" type="{http://www.w3.org/2001/XMLSchema}NCName" />
     *     &lt;/restriction>
     *   &lt;/complexContent>
     * &lt;/complexType>
     * </pre>
     * 
     * 
     */
    @XmlAccessorType(XmlAccessType.FIELD)
    @XmlType(name = "", propOrder = {
        "content"
    })
    @XmlRootElement(name = "span")
    public class Span {
    
        @XmlElementRef(name = "div", type = Div.class)
        @XmlMixed
        protected List<Object> content;
        @XmlAttribute
        @XmlJavaTypeAdapter(CollapsedStringAdapter.class)
        @XmlSchemaType(name = "NCName")
        protected String id;
    
        /**
         * Gets the value of the content property.
         * 
         * <p>
         * 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 <CODE>set</CODE> method for the content property.
         * 
         * <p>
         * For example, to add a new item, do as follows:
         * <pre>
         *    getContent().add(newItem);
         * </pre>
         * 
         * 
         * <p>
         * Objects of the following type(s) are allowed in the list
         * {@link Div }
         * {@link String }
         * 
         * 
         */
        public List<Object> getContent() {
            if (content == null) {
                content = new ArrayList<Object>();
            }
            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 <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 javax.xml.bind.annotation.XmlRegistry;
    
    
    /**
     * This object contains factory methods for each 
     * Java content interface and Java element interface 
     * generated in the example package. 
     * <p>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();
        }
    
    }