我正在尝试使用jaxb将以下xml绑定到Java
<Validation>
...
<Options>
<AllowUnspecifiedParameters>
<Header> True </Header>
<Query> True </Query>
<Cookies> True </Cookies>
</AllowUnspecifiedParameters>
</Options>
</Validation>
我看过类似的例子,例如JAXB binding nested elements 但是最深层的嵌套级别是用于列表的,@XmlElementWrapper仅用于集合,因此看起来不适合我的情况。
有人知道我该怎么做吗?真的很感激。
答案 0 :(得分:1)
选项1 的一种纯JaxB方法是通过为Options元素定义适配器。适配器用于将任何xml或多或少地转换为任何对象,反之亦然(自定义封送处理)。
@XmlJavaTypeAdapter(OptionsAdapter.class)
public class OptionsAdapter extends extends XmlAdapter<Element, Options> {
@Override
public Element marshal(Options v) throws Exception {
// put your marshaling logic here
}
@Override
public Options unmarshal(Element node) throws Exception {
// put your unmarshaling logic here
}
}
Then in the class holding the options element you will have:
public class ClazzHoldingOptions {
@XmlJavaTypeAdapter(OptionsAdapter.class)
private Options options;
}
选项2 EclipseLink具有通过xpath表达式映射元素的功能
@XmlPath("AllowUnspecifiedParameters/Header/text()")
private String header;
https://www.eclipse.org/eclipselink/api/2.4/org/eclipse/persistence/oxm/annotations/XmlPath.html
选项3 在阅读@ df778899的代码时,我认为他的解决方案不是最佳的,但是它解决了我到目前为止尚未解决的问题。就是当您拥有如此多的属性时,您实际上并不想映射它们,或者只是简单地无法控制XML内容并且不信任它,也不想破坏更改。在其中我将映射到HashMap:
@XmlJavaTypeAdapter(OptionsAdapter.class)
public class OptionsAdapter extends extends XmlAdapter<Element, Options> {
@Override
public Element marshal(Hashmap v) throws Exception {
// put your marshaling logic here
}
@Override
public HashMap unmarshal(Element node) throws Exception {
// put your unmarshaling logic here
}
}
Then in the class holding the options element you will have:
public class ClazzHoldingOptions {
@XmlJavaTypeAdapter(OptionsAdapter.class)
private HashMap options;
}
摘要。因此,让我总结一下优缺点
选项1。 +标准Aproach纯jaxB +好,如果您拥有xml文件的架构的控制权。或者,如果预计该架构每月不会更改。 -如果架构或xml文件非常不稳定,则错误。
选项2。 +非常易于使用。无需适配器。 -如果您的架构易变,则不是最佳解决方案。 -需要特定的JaxB实现
选项3。-仅当您具有用于避免重大更改的易失性xml时,才有用。
PS:我使用@ df778899解决方案之类的唯一情况是,XML的结构是否存在极端结构性不确定性。例如,如果我知道xml中会出现某些内容,但我不知道确切的位置。 PLus内存不足,是否要在内存中保存与xml相关的所有元数据。
答案 1 :(得分:1)
您可以使用@XmlAnyElement
提供嵌套元素,尽管它们以相当原始的形式出现-例如org.w3c.dom.Element
实例:
@XmlRootElement(name = "Validation")
public class Validation {
private List<Element> options;
@XmlElementWrapper(name = "Options")
@XmlAnyElement
public List<Element> getOptions() {
return options;
}
...
}
然后可以将数据深入到:
Validation validation = (Validation) unmarshaller.unmarshal(source);
for (Element element : validation.getOptions()) {
System.out.println(element.getNodeName() + ":");
NodeList childNodes = element.getChildNodes();
for (int i = 0; i < childNodes.getLength(); i++) {
Node childNode = childNodes.item(i);
if (childNode.getNodeType() == Node.ELEMENT_NODE)
System.out.println(" " + childNode.getNodeName() + "=" +
childNode.getTextContent());
}
}
其中显示了所有通过的数据:
AllowUnspecifiedParameters:
Header= True
Query= True
Cookies= True
答案 2 :(得分:0)
原来我的问题有一个简单的答案:
XML:
<Validation>
...
<Options>
<AllowUnspecifiedParameters>
<Header> True </Header>
<Query> True </Query>
<Cookies> True </Cookies>
</AllowUnspecifiedParameters>
</Options>
</Validation>
Java对象:
@XmlRootElement(name = "Validation")
public class Validation {
// some more fields
// ...
private Options option = new Options();
@XmlElement(name = "Options")
public Options getOptions() {
return options;
}
}
public class Options {
@XmlElement(name = "AllowUnspecifiedParameters")
public StrictOptions allowUnspecifiedParameters = new StrictOptions();
public static class StrictOptions {
@XmlElement(name = "Header")
public boolean header = true;
@XmlElement(name = "Query")
public boolean query = true;
@XmlElement(name = "Cookie")
public boolean cookie = true;
}
}
但是,如果您有一个非常复杂的xml模式或java对象结构,如@ df778899和@Alexandar Petrov建议的那样,XmlAdapter
和@ XmlAnyElement
是强大的工具。
以下是我发现的一个示例:Mapping an Arbitrary List of Objects Using JAXB's @XmlAnyElement and XmlAdapter