【问题标题】:JAXB unmarshaling with namespaces.. how?JAXB 使用命名空间解组.. 怎么样?
【发布时间】:2017-03-18 12:56:31
【问题描述】:

假设我的有效 xml 如下所示:

<A xmlns="something">
   <B>4</B>
</A>

我的代码是这样的:

@XmlRootElement(name = "A")
@XmlAccessorType (XmlAccessType.FIELD)
@Getter //from lombok
public class Data{

@XmlElement(name = "B")
private String b;

public Data(String b) {
    this.b = b;
}

public Data() {
}
// Getter/setter generated by lombok.
}

如何让它工作?如果我的 xml 标记有一些关联元素,例如上面的“xmlns”,则 JAXB 解组器会引发异常。

我是第一次这样做,所以我真的对 JAXB、解组等一无所知。我在挣扎。 :) 任何帮助都会很好。

编辑 堆栈跟踪:

javax.xml.bind.UnmarshalException: unexpected element (uri:"something", local:"A"). Expected elements are <{}B>,<{}A>
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:726)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:247)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:242)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Loader.reportUnexpectedChildElement(Loader.java:109)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext$DefaultRootLoader.childElement(UnmarshallingContext.java:1131)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext._startElement(UnmarshallingContext.java:556)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.startElement(UnmarshallingContext.java:538)
at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.startElement(SAXConnector.java:153)
at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.startElement(AbstractSAXParser.java:509)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.scanStartElement(XMLNSDocumentScannerImpl.java:374)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl$NSContentDriver.scanRootElementHook(XMLNSDocumentScannerImpl.java:613)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3132)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$PrologDriver.next(XMLDocumentScannerImpl.java:852)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:602)
at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(XMLNSDocumentScannerImpl.java:112)
at   com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:505)
at ...

【问题讨论】:

  • 你能发布你的代码和异常吗?
  • b字段不需要getter和setter方法吗?
  • 确实如此,我正在使用 lombok。 :) @Getter 注释来自 lombok。

标签: java xml jaxb unmarshalling


【解决方案1】:

来自XmlRootElement 的来源:

public @interface XmlRootElement {
    /**
     * namespace name of the XML element.
     * <p>
     * If the value is "##default", then the XML namespace name is derived
     * from the package of the class ( {@link XmlSchema} ). If the
     * package is unnamed, then the XML namespace is the default empty
     * namespace.
     */
    String namespace() default "##default";
     // else of file

您还应该记住,此规则也适用于大多数 JAXB 注释,因此您需要指定根元素以及其他元素,并明确给出命名空间,如下所示:

@XmlRootElement(namespace="something", name = "A")
@XmlAccessorType (XmlAccessType.FIELD)
@Getter //from lombok
public class Data{
    @XmlElement(namespace="something", name = "B") // <-- mind this
    private String b;

    public Data(String b) {
        this.b = b;
    }

    public Data() {
    }
    // Getter/setter generated by lombok.
}

如果你不这样做,它会期望,假设你的Dataorg.example 包中,命名空间org.example 中的一些元素只要你有@XmlSchema(elementFormDefault=QUALIFIED),或者它将需要默认命名空间中的元素。

【讨论】:

  • 哦,好吧!如果我有多个不同的命名空间怎么办?
  • 然后你更改对应的XmlRootElementXmlElementXmlAttribute等的命名空间属性。
  • 我的意思是,我有
  • 我假设您的 xsi 指的是 XMLSchema-Instance 命名空间。然后您将添加一个字符串字段并使用@XmlAttribute(namespace=java.xml.XMLConstants.W3C_XML_SCHEMA_INSTANCE_NS_URI, name="type") 对其进行注释以获取您在xsi:type 属性中设置的值。
  • 哦!所以命名空间都是一些已经定义为 xml 格式的一部分的元素。好吧。我不知道。非常感谢!一旦我开始解组工作,我会将其标记为答案。如果我不能让它工作,我会回到这里。
【解决方案2】:

如果您的 xml 文档中有命名空间,那么您的 jaxb 注释中也需要有它。

例如像这样:

@XmlRootElement(name = "A", namespace="something")
@XmlAccessorType (XmlAccessType.FIELD)
public class Data{

【讨论】:

  • 好吧.. 另一个问题,如果我有多个“命名空间”怎么办?像 >
【解决方案3】:

您只需将@XmlAttribute 添加到A(与相应的getter/setter 对齐)

@XmlRootElement(name = "A")
@XmlAccessorType (XmlAccessType.FIELD)
@Getter //from lombok
public class Data{

@XmlAttribute(name="xmln")
String attr;
@XmlElement(name = "B")
private String b;

public Data(String b) {
    this.b = b;
}

   public Data() {
 }
// Getter/setter generated by lombok.
    public String getAttr(){
    return attr;
    }
    public void setAttr(String attr){
    this.attr = attr;
  }
  }

编辑:这不能回答问题,因为问题是关于 xml 命名空间而不是属性。

【讨论】:

  • 这篇文章充分展示了你是如何不了解xml是什么。
  • 这不是,@dsp_user
  • 是的,我以为您一般对 xml 属性感兴趣,而不是对 xml 命名空间感兴趣。对不起
  • 如果您确实检查了异常消息,您很快就会知道问题是限定名称不匹配,而不是缺少导致解组器抱怨的属性。
  • 好吧,我很仓促。我们有时都会这样做,不是吗? (提到网址的例外情况非常有启发性)
猜你喜欢
  • 2014-11-07
  • 2015-04-25
  • 2013-10-24
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多