当前位置: 首页 > 知识库问答 >
问题:

既可选又可为零的JAXB元素

姬衡
2023-03-14

这就给了我一个可以调用的web服务。它使我对发送和返回的xml有了更多的控制,而且还自动完成了编写完整WSDL所需的重复操作。

问题
在模式中,我有一个如下的元素:

<xs:element name="myElement" type="xs:string" nillable="true" minOccurs="0" /> 

所以我想区分用户设置null或blank。然后生成的类具有此属性。

@XmlElementRef(name = "myElement", namespace = "/mynamespace", type = JAXBElement.class)
protected JAXBElement<String> myElement;
@XmlElement(required = true, nillable = true)
protected String myElement;
protected String myElement

我还尝试手动更改生成的类,使其看起来像这样。

@XmlElementRef(name = "myElement", namespace = "/mynamespace", type = JAXBElement.class, required=false)
protected JAXBElement<String> myElement;

现在这个元素是可选的,但是我仍然不能将它设置为NIL。这样做会导致JAXBElement的值为空白字符串。只有当您关闭模式验证时,才会这样做,因为生成的JAX-WS WSDL/schema没有将元素设置为nillable,所以它不是一个有效的请求。

摘要
我认为这是JAXB的一个bug。@XmlElementRef注释有一个属性将其设置为not required,但没有属性将该字段设置为nullable。

另外
我使用的是jaxb 2.2.6,而maven插件是jaxb2-maven-plugin1.5。

共有1个答案

洪凯定
2023-03-14

对于

@XmlElementRef(name="foo", required=false)
protected JAXBElement<String> foo;

文档中缺席的节点将对应于此字段为NULL。文档中包含xsi:nil=“true”的XML元素将对应于JaxBelement的实例,其值为null

您还可以提供XML模式,而不是让JAXB使用包级别@xmlschema注释上的location属性生成模式。

@XmlSchema(
    ...
    location="http://www.example.com/schema/root.xsd")
package forum19665550;

import javax.xml.bind.annotation.XmlSchema;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    @XmlElementRef(name="foo", required=false)
    protected JAXBElement<String> foo;

    @XmlElementRef(name="bar", required=false)
    protected JAXBElement<String> bar;

}
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;

@XmlRegistry
public class ObjectFactory {

    @XmlElementDecl(name="foo")
    public JAXBElement<String> createFoo(String foo) {
        return new JAXBElement<String>(new QName("foo"), String.class, foo);
    }

    @XmlElementDecl(name="bar")
    public JAXBElement<String> createBar(String bar) {
        return new JAXBElement<String>(new QName("bar"), String.class, bar);
    }

}

演示

下面的演示代码将研究foobar值的差异。可以使用JAXBIntrospector类获取JAXBelement实例的实际值。EclipseLink JAXB(MOXy)中有一个bug与解组包裹空值的JAXBelement实例有关(请参见http://bugs.eclipse.org/420746)。

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

public class Demo {

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

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        File xml = new File("src/forum19665550/input.xml");
        Root root = (Root) unmarshaller.unmarshal(xml);

        System.out.println("foo was set:          " + (root.foo != null));
        System.out.println("bar was set:          " + (root.bar != null));
        System.out.println("foo value:            " + root.foo);
        System.out.println("bar value:            " + root.bar);
        System.out.println("foo unwrapped value:  " + JAXBIntrospector.getValue(root.foo));
        System.out.println("bar unwrapped value:  " + JAXBIntrospector.getValue(root.bar));

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

}

input.xml/output

foo was set:          false
bar was set:          true
foo value:            null
bar value:            javax.xml.bind.JAXBElement@4af42ea0
foo unwrapped value:  null
bar unwrapped value:  null
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
    <bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
import java.io.IOException;
import javax.xml.bind.*;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;

public class GenerateSchema {

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

        jc.generateSchema(new SchemaOutputResolver() {

            @Override
            public Result createOutput(String namespaceUri,
                    String suggestedFileName) throws IOException {
                StreamResult result = new StreamResult(System.out);
                result.setSystemId(suggestedFileName);
                return result;
            }

        });
    }

}

下面是产生的XML模式。您没有指出foobar元素是可零的,这是正确的。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="bar" type="xs:string"/>

  <xs:element name="foo" type="xs:string"/>

  <xs:element name="root" type="root"/>

  <xs:complexType name="root">
    <xs:sequence>
      <xs:element ref="foo" minOccurs="0"/>
      <xs:element ref="bar" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

不必让JAXB从您的模型派生XML模式,您可以指向包含更多信息的现有模式。

包信息

@XmlSchema(
    ...
    location="http://www.example.com/schema/root.xsd")
package forum19665550;

import javax.xml.bind.annotation.XmlSchema;
 类似资料:
  • 类似于element select组件allow-create属性,即输入后下拉列表匹配到数据时则选择,没有匹配则创建条目然后供选择。但现在的需求是,不想要创建条目后手动再选择一下,而是直接失去焦点后创建。 想要的效果:一个组件,输入文字后下拉列表有匹配则用户手动选择,没有匹配到则失去焦点后直接创建.

  • 如果该方法是可选的,则意味着(我假设)它不必实现。但是,抽象方法必须由具体的类实现。我错过了什么?他们的意思是我们可以有空的方法吗?

  • 问题内容: 我正在将JTable放入JScrollPane 但是,当我设置JTable Auto Resizeable时,它将没有水平滚动条。 如果我设置了AUTO_RESIZE_OFF,那么当列宽不够大时,Jtable将不会填充其容器的宽度。 所以我该怎么做: 当表格不够宽时,展开以填充其容器宽度 当表格足够宽时,使其可滚动。 谢谢 问题答案: 您需要自定义Scrollable界面的行为。 上面

  • 本文向大家介绍PowerShell函数参数设置为即可选又必选的方法,包括了PowerShell函数参数设置为即可选又必选的方法的使用技巧和注意事项,需要的朋友参考一下 本文介绍PowerShell自定义函数中使用参数集时,可以将同一个参数既设置为可选,又设置为必选。 好吧,小编承认,这个话题有点无聊,但确实还是有点有趣,不妨看一看啦。 在PowerShell中,我们有可能有这样的需求,如果只需要输

  • 当使用Java8类时,有两种方法可以将值包装到Optional中。 我理解是使用的唯一安全方法,但为什么?为什么不直接使用

  • 如何使用JAXB生成以下结构?在我的例子中,我有一个动态属性列表,它可能有3种类型:整数、字符串或列表。但是,列表属性具有嵌套元素。我怎样才能做到这一点?