• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

JAXB使用java对象层次结构表示嵌套的模型组架构组件

用户头像
it1352
帮助1

问题说明

Schema允许设计者指定子元素的可选序列,如下所示;

Schema allows a designer to specify optional sequences of child elements as follows;

<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/Schema1" xmlns:tns="http://www.example.org/Schema1" elementFormDefault="qualified">

    <complexType name="RootType">
        <sequence>
            <choice>
                <sequence minOccurs="1" maxOccurs="1">
                    <element name="A" type="tns:A"></element>
                    <element name="B" type="tns:B"></element>
                    <element name="C" type="tns:C"></element>
                </sequence>
                <element name="P" type="tns:P" minOccurs="1" maxOccurs="1"></element>
                <element name="Q" type="tns:Q" minOccurs="1" maxOccurs="1"></element>
            </choice>
        </sequence>
    </complexType>

    <complexType name="A">
        <sequence>
            <element name="one" type="string"/>
            <element name="two" type="string"/>
            <element name="three" type="string"/>
        </sequence>
    </complexType>

    <complexType name="B">
        <sequence>
            <element name="one" type="string"/>
            <element name="two" type="string"/>
            <element name="three" type="string"/>
        </sequence>
    </complexType>

    <complexType name="C">
        <sequence>
            <element name="one" type="string"/>
            <element name="two" type="string"/>
            <element name="three" type="string"/>
        </sequence>
    </complexType>

    <complexType name="P">
        <sequence>
            <element name="one" type="string"/>
            <element name="two" type="string"/>
            <element name="three" type="string"/>
        </sequence>
    </complexType>

    <complexType name="Q">
        <sequence>
            <element name="one" type="string"/>
            <element name="two" type="string"/>
            <element name="three" type="string"/>
        </sequence>
    </complexType>

    <element name="TopLevel" type="tns:RootType"></element>
</schema>

此验证

<?xml version="1.0" encoding="UTF-8"?>
<tns:TopLevel xmlns:tns="http://www.example.org/Schema1">
    <tns:A>
        <tns:one>tns:one</tns:one>
        <tns:two>tns:two</tns:two>
        <tns:three>tns:three</tns:three>
    </tns:A>
    <tns:B>
        <tns:one>tns:one</tns:one>
        <tns:two>tns:two</tns:two>
        <tns:three>tns:three</tns:three>
    </tns:B>
    <tns:C>
        <tns:one>tns:one</tns:one>
        <tns:two>tns:two</tns:two>
        <tns:three>tns:three</tns:three>
    </tns:C>
</tns:TopLevel>

并拒绝

<?xml version="1.0" encoding="UTF-8"?>
<tns:TopLevel xmlns:tns="http://www.example.org/Schema1">
    <tns:A>
        <tns:one>tns:one</tns:one>
        <tns:two>tns:two</tns:two>
        <tns:three>tns:three</tns:three>
    </tns:A>
    <tns:B>
        <tns:one>tns:one</tns:one>
        <tns:two>tns:two</tns:two>
        <tns:three>tns:three</tns:three>
    </tns:B>
</tns:TopLevel>

   <?xml version="1.0" encoding="UTF-8"?>
    <tns:TopLevel xmlns:tns="http://www.example.org/Schema1">
        <tns:A>
            <tns:one>tns:one</tns:one>
            <tns:two>tns:two</tns:two>
            <tns:three>tns:three</tns:three>
        </tns:A>
        <tns:B>
            <tns:one>tns:one</tns:one>
            <tns:two>tns:two</tns:two>
            <tns:three>tns:three</tns:three>
        </tns:B>
        <tns:C>
            <tns:one>tns:one</tns:one>
            <tns:two>tns:two</tns:two>
            <tns:three>tns:three</tns:three>
        </tns:C>
        <tns:P>
            <tns:one>tns:one</tns:one>
            <tns:two>tns:two</tns:two>
            <tns:three>tns:three</tns:three>
        </tns:P>
    </tns:TopLevel>

当然,如果我从中生成一个JAXB类,我得到

Ofcourse if I generate a JAXB class from this I get

...
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "RootType", propOrder = {
    "a",
    "b",
    "c",
    "p",
    "q"
})
//Manually added for testing 
@XmlRootElement(name="TopLevel")
public class RootType {

    @XmlElement(name = "A")
    protected A a;
    @XmlElement(name = "B")
    protected B b;
    @XmlElement(name = "C")
    protected C c;
    @XmlElement(name = "P")
    protected P p;
    @XmlElement(name = "Q")
    protected Q q;

    /**
     * Gets the value of the a property.
     * 
     * @return
     *     possible object is
     *     {@link A }
     *     
     */
    public A getA() {
        return a;
    }

    /**
     * Sets the value of the a property.
     * 
     * @param value
     *     allowed object is
     *     {@link A }
     *     
     */
    public void setA(A value) {
        this.a = value;
    }

    ....

    etc.

如果我没有在Unmarshaller上设置Schema验证,它将加载所有3个实例而不会抱怨。

which will load all 3 instances without complaining provided if I don't set up the Schema validation on the Unmarshaller.

然后java实例是相反的到Schema,以下将失败。即使它有效,我也必须做额外的工作来确定RootType实例所处的状态。

The java instance is then contrary to the Schema, and the following will fail. Even if it is valid I must do extra work to determine what state the RootType instance is in.

private static void validate(uk.co.his.test.complexSequenceAndChoice.generated.nact1moxy.RootType root)
{
    if(root.getA()!=null)
    {
        Assert.assertTrue("RootType should either be a sequence of A, B, C or a sinle P or a single Q", root.getB()!=null&&root.getC()!=null&&root.getP()==null&&root.getQ()==null);
    }
    else
    {
        Assert.assertTrue("RootType should either be a sequence of A, B, C or a sinle P or a single Q", root.getB()==null&&root.getC()==null
                &&((root.getP()!=null&&root.getQ()==null)
                || (root.getP()==null&&root.getQ()!=null)));
    }
}

问题是:

    • 无论如何在Java类层次结构中更准确地表示这一点?
      通常模型组架构组件指定子元素的排序,但是,如果嵌套的模型组模式组件指定了更复杂的排序,Java只能捕获所有子项的桶?
  • Is there anyway to represent this more accurately in a Java class hierachy? Generally Model Group Schema Components specify the ordering of child elements, but Java can only capture the 'bucket of all children' in cases where more complex orderings are specified by nested Model Group Schema components?

困难在于我们希望通过一对一方式不与Element解析事件绑定的java类来表示这些分组;

The difficulty is we would like to represent these groupings by java classes that do not bind to Element parsing events in a one to one way;

想象一下存在一个@XmlElementSequence注释允许指定一系列子项;

Imagine a @XmlElementSequence annotation existed that allowed a sequence of children to be specified;

package uk.co.his.test.complexSequenceAndChoice.manual5;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElements;
import javax.xml.bind.annotation.XmlType;

@XmlType(name = "RootType")
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
public class RootType {

    @XmlElements({
        @XmlElementSequence(Sequencepart.class), 
        @XmlElement(name="P", type=P.class), 
        @XmlElement(name="Q", type=Q.class)
        })
    public Object partA;

}


package uk.co.his.test.complexSequenceAndChoice.manual5;

import javax.xml.bind.annotation.XmlElement;

import uk.co.his.test.complexSequenceAndChoice.generated.nact1.A;
import uk.co.his.test.complexSequenceAndChoice.generated.nact1.B;

@XmlElementSequenceDef(propOrder = {
    "a",
    "b",
    "c"
})
public class Sequencepart {

    @XmlElement(name = "A")
    protected A a;
    @XmlElement(name = "B")
    protected B b;
    @XmlElement(name = "C")

}

编组人员会相对简单。 Unmarshaller必须知道在看到A元素标记的开始时创建一个Sequencepart,并在该Sequencepart实例中插入A值。

The marshaller would be relatively simple. The Unmarshaller would have to know to create a Sequencepart when it saw the start of an "A" element tag, and to insert the A values inside that Sequencepart instance.

I已经在MOXy网站上询问了这个,并提供了一个示例Maven项目。

I have asked this on the MOXy site, and included a sample Maven project.

正确答案

#1

这可以使用MOXy特定注释来完成。

This can be done using MOXy specific annotations.

请参阅创建自我映射部分此处了解更多信息详细信息。

See the section "Creating "Self" Mappings" here for more detail.

如果我使用MOXy @XmlPath注释注释我的JAXB类,如下所示;

If I annotate my JAXB class with the MOXy @XmlPath annotation as follows;

import java.util.Optional;

import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;

import org.eclipse.persistence.oxm.annotations.XmlPath;



@XmlAccessorType(XmlAccessType.NONE)
@XmlType(name = "RootType", propOrder = {
    "seq1",
    "p",
    "q"
})
@XmlRootElement(name="TopLevel")
public class RootType {


    @XmlPath(".")
    private InnerSequence seq1;
    @XmlElement(name = "P")
    private P p;
    @XmlElement(name = "Q")
    private Q q;

    public static class InnerSequence 
    {
        @XmlElement(name = "A")
        public A a;
        @XmlElement(name = "B")
        public B b;
        @XmlElement(name = "C")
        public C c;

        public boolean isEmpty() {
            return c==null&&b==null&&a==null;
        }
        ...
    }
...

我现在可以创建针对架构验证的XML;

I can now create XML that validates against the schema;

<?xml version="1.0" encoding="UTF-8"?>
<TopLevel xmlns="http://www.example.org/Schema1">
   <A>
      <one>Hello One A</one>
   </A>
   <B>
      <one>Hello One B</one>
   </B>
   <C>
      <one>Hello One C</one>
   </C>
</TopLevel>

请注意,MOXy将在Unmarshalling期间使用InnerSequence实例填充seq1,无论文件是否包含任何A ,B或Cs。

Note that MOXy will populate seq1 with an instance of InnerSequence during Unmarshalling regardless of whether the file contains any A, B or Cs.

该文件;

<?xml version="1.0" encoding="UTF-8"?>
<TopLevel xmlns="http://www.example.org/Schema1">
   <P>
      <one>Hello One A</one>
   </P>
</TopLevel>

仍然使用InnerSequence填充seq1。

still populates seq1 with an InnerSequence.

我发布到Eclipselink论坛的答案附有Maven项目提供更多(工作细节)

The answer I posted to the Eclipselink forum has an attached Maven project which gives more (working details)

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tanhbiaghk
系列文章
更多 icon
同类精品
更多 icon
继续加载