1

Input:

<?xml version="1.0" encoding="UTF-8"?>
<foo:root xmlns:foo="http://www.domain.org/foo" 
      xmlns="http://www.domain.org/foo"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema#"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <a xsi:type="foo:someType">
   <b  text="some text" />
  </a>
</foo:root>

Bindings:

<?xml version="1.0"?>
<xml-bindings
   xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
   package-name="test">

<xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
    <xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
</xml-schema>

 <java-types>        
    <java-type name="Root">
        <xml-root-element name="root"/>
        <java-attributes>
            <xml-element java-attribute="contentRoot" xml-path="." type="test.ContentRoot" />
        </java-attributes>
    </java-type>

    <java-type name="ContentRoot">
        <java-attributes>
            <xml-element java-attribute="text" xml-path="a/b/@text" />
            <xml-element java-attribute="contents" xml-path="a/b" type="test.Content" container-type="java.util.List" />
        </java-attributes>
    </java-type>

    <java-type name="Content">
        <java-attributes>
            <xml-element java-attribute="text" xml-path="@text" />
        </java-attributes>
    </java-type>
</java-types>

</xml-bindings>

Classes in package test:

public class Root {
 private List<ContentRoot> contentRoots = new LinkedList<ContentRoot>();
 public List<ContentRoot> getContentRoots() {
    return contentRoots;
 } 
 public void setContentRoots(List<ContentRoot> contentRoots) {
    this.contentRoots = contentRoots;
 }
 public void setContentRoot(ContentRoot contentRoot) {
    this.contentRoots.add(contentRoot);
 }
}

public class ContentRoot {
 private List<Content> contents;
 private String text;
 public List<Content> getContents() {
    return contents;
 }
 public void setContents(List<Content> contents) {
    this.contents = contents;
 }
 public String getText() {
    return text;
 }
 public void setText(String text) {
    this.text = text;
 }  
}

public class Content  {
 private String text;
 public String getText() {
    return text;
 }
 public void setText(String text) {
    this.text = text;
 }
}

Running Code:

Map<String, Object> jaxbContextProperties = new HashMap<String, Object>(1);
jaxbContextProperties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "bindings.xml");
JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {Root.class}, jaxbContextProperties);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root)unmarshaller.unmarshal(new File("input.xml"));
System.out.println(root.getContentRoots().get(0).getText());    
System.out.println(root.getContentRoots().get(0).getContents().get(0).getText());

The result is, that text is set in ContentRoot but not in Content (I get a NullPointerException from the last System.out.println()). Can somebody tell me why?

4

1 回答 1

1

有几个项目让你绊倒:

ISSUE #1 -ContentRoot包含无效的映射

EclipseLink JAXB (MOXy)不允许以下映射组合。第二个xml-element是告诉 MOXy 将属性映射中出现contents的重复。第一个元素之一的 text 属性映射property。baxml-elementbStringtext

<java-type name="ContentRoot">
    <java-attributes>
        <xml-element java-attribute="text" xml-path="a/b/@text" />
        <xml-element java-attribute="contents" xml-path="a/b" type="test.Content" container-type="java.util.List" />
    </java-attributes>
</java-type>

text映射属性的正确位置是在Content您已经拥有的类上。我建议不要使用指向属性的xml-element映射(这会起作用),而是建议使用映射并指定.xml-pathxml-attributename

<java-type name="Content">
    <java-attributes>
        <xml-attribute java-attribute="text"/>
    </java-attributes>
</java-type>

ISSUE #2 -xml-path没有正确的命名空间限定

由于bindings.xml您已将foo前缀与http://www.domain.org/foo命名空间 URI 相关联。

<xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
    <xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
</xml-schema>

当您指定时,xml-path您需要包含前缀以获得正确的命名空间限定。

<java-type name="ContentRoot">
    <java-attributes>
        <xml-element java-attribute="contents" xml-path="foo:a/foo:b"/>
    </java-attributes>
</java-type>

了解更多信息

或者,您可以将其映射xml-element-wrapper为如下:

<java-type name="ContentRoot">
    <java-attributes>
        <xml-element java-attribute="contents" name="b">
            <xml-element-wrapper name="a"/>
        </xml-element>
    </java-attributes>
</java-type>

问题 #3 -xml-path="."不能用于集合属性

目前 MOXy 要求集合中的每个项目都对应于它自己的元素。这意味着此时您不能.为集合属性指定self XPath。


完整示例

您的演示代码似乎与您的域模型不完全匹配。这是一个将所有内容组合在一起的完整示例:

package test;

public class Root {

    private ContentRoot contentRoot;

    public ContentRoot getContentRoot() {
        return contentRoot;
    }

    public void setContentRoot(ContentRoot contentRoot) {
        this.contentRoot = contentRoot;
    }

}

内容根

package test;

import java.util.List;

public class ContentRoot {

    private List<Content> contents;

    public List<Content> getContents() {
        return contents;
    }

    public void setContents(List<Content> contents) {
        this.contents = contents;
    }

}

内容

package test;

public class Content {

    private String text;

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

}

绑定.xml

<?xml version="1.0"?>
<xml-bindings xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
    package-name="test"
    xml-accessor-type="FIELD">

    <xml-schema element-form-default="QUALIFIED" namespace="http://www.domain.org/foo">
        <xml-ns prefix="foo" namespace-uri="http://www.domain.org/foo" />
    </xml-schema>

    <java-types>
        <java-type name="Root">
            <xml-root-element/>
            <java-attributes>
                <xml-element java-attribute="contentRoot" xml-path="."/>
            </java-attributes>
        </java-type>

        <java-type name="ContentRoot">
            <java-attributes>
                <xml-element java-attribute="contents" xml-path="foo:a/foo:b"/>
            </java-attributes>
        </java-type>

        <java-type name="Content">
            <java-attributes>
                <xml-attribute java-attribute="text"/>
            </java-attributes>
        </java-type>
    </java-types>

</xml-bindings>

演示

package test;

import java.io.File;
import java.util.*;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.JAXBContextFactory;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> jaxbContextProperties = new HashMap<String, Object>(1);
        jaxbContextProperties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "test/bindings.xml");
        JAXBContext jaxbContext = JAXBContextFactory.createContext(new Class[] {Root.class}, jaxbContextProperties);

        Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
        Root root = (Root)unmarshaller.unmarshal(new File("src/test/input.xml"));
        System.out.println(root.getContentRoot().getContents().get(0).getText());

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

}
于 2013-07-31T14:01:19.007 回答