JAXB/XSD:数字而不是元素名称
JAXB/XSD: Number instead of Element name
我必须从 xml 文件创建 Java 个对象(转换前我无法编辑),所以我认为最好创建一个 XSD 然后通过 JAXB 解组文件。
问题是,XML 中有一些元素的格式如下:
<parent-element>
<id-00001>...</id-00001>
<id-00002>...</id-00002>
...
</parent-element>
所以基本上我有一个 xml 元素的列表,元素的 "name" 是列表内部的顺序。每个列表中的元素数量可能不受限制。
是否可以使用 JAXB 解组,或者我是否必须使用 XML-Reader 并循环遍历元素? "id-XXXXX" 元素在内部都以相同的方式格式化,因此如果将其格式化为 "" 则可能没有任何问题。
提前致谢!
由于您的 xml 可能有无限数量的 "id-elements",因此创建匹配的 POJO 结构很棘手。您可以使用 @XmlAnyElement
和适配器。 @XmlAnyElement
会将不同的元素读取为 dom 个节点,您可以在适配器中处理它们。
例如,下面给出 xml:
<parent-element>
<id-00001>value 1</id-00001>
<id-00002>value 2</id-00002>
</parent-element>
您的根可能如下所示:
@XmlRootElement(name = "parent-element")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlAnyElement
@XmlJavaTypeAdapter(MyAdapter.class)
private List<String> varyingElements;
}
你的适配器是这样的:
public class MyAdapter extends XmlAdapter<Element, String> {
@Override
public Element marshal(String arg0) throws Exception {
// do what you must
return null;
}
@Override
public String unmarshal(Element element) throws Exception {
return element.getChildNodes().item(0).getNodeValue();
}
}
元素如 org.w3c.dom.Element
我猜你的 XML
负载如下所示:
<root>
<parent-element>
<id-00001>value 1</id-00001>
<id-00002>value 2</id-00002>
</parent-element>
</root>
要读取具有动态名称的节点,我们需要编写自定义适配器 (javax.xml.bind.annotation.adapters.XmlAdapter
)。假设模型如下所示:
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
class Root {
@XmlElement(name = "parent-element")
@XmlJavaTypeAdapter(IdsXmlAdapter.class)
private MultiItemList list;
// getters, setters, toString
}
class MultiItemList {
private List<String> ids;
// getters, setters, toString
}
对于以上 XML
和 POJO
模型自定义适配器可能如下所示:
class IdsXmlAdapter extends XmlAdapter<Object, MultiItemList> {
@Override
public MultiItemList unmarshal(Object v) {
Element element = (Element) v;
NodeList childNodes = element.getChildNodes();
List<String> ids = new ArrayList<>(childNodes.getLength());
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
if (item.getNodeName().equals("#text")) {
continue;
}
ids.add(item.getTextContent());
}
MultiItemList multiItemList = new MultiItemList();
multiItemList.setIds(ids);
return multiItemList;
}
@Override
public Object marshal(MultiItemList v) throws Exception {
return null; // Implement if needed
}
}
用法示例:
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.bind.JAXBContext;
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.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
public class JaxbApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Object unmarshal = jaxbContext.createUnmarshaller().unmarshal(new FileReader(xmlFile));
System.out.println(unmarshal);
}
}
打印:
Root{list=Root{ids=[value 1, value 2]}}
注意,您不能直接实施 XmlAdapter<Element, MultiItemList>
适配器,因为异常:
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
org.w3c.dom.Element is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at org.w3c.dom.Element
另请参阅:
我必须从 xml 文件创建 Java 个对象(转换前我无法编辑),所以我认为最好创建一个 XSD 然后通过 JAXB 解组文件。 问题是,XML 中有一些元素的格式如下:
<parent-element>
<id-00001>...</id-00001>
<id-00002>...</id-00002>
...
</parent-element>
所以基本上我有一个 xml 元素的列表,元素的 "name" 是列表内部的顺序。每个列表中的元素数量可能不受限制。 是否可以使用 JAXB 解组,或者我是否必须使用 XML-Reader 并循环遍历元素? "id-XXXXX" 元素在内部都以相同的方式格式化,因此如果将其格式化为 "" 则可能没有任何问题。
提前致谢!
由于您的 xml 可能有无限数量的 "id-elements",因此创建匹配的 POJO 结构很棘手。您可以使用 @XmlAnyElement
和适配器。 @XmlAnyElement
会将不同的元素读取为 dom 个节点,您可以在适配器中处理它们。
例如,下面给出 xml:
<parent-element>
<id-00001>value 1</id-00001>
<id-00002>value 2</id-00002>
</parent-element>
您的根可能如下所示:
@XmlRootElement(name = "parent-element")
@XmlAccessorType(XmlAccessType.FIELD)
public class Root {
@XmlAnyElement
@XmlJavaTypeAdapter(MyAdapter.class)
private List<String> varyingElements;
}
你的适配器是这样的:
public class MyAdapter extends XmlAdapter<Element, String> {
@Override
public Element marshal(String arg0) throws Exception {
// do what you must
return null;
}
@Override
public String unmarshal(Element element) throws Exception {
return element.getChildNodes().item(0).getNodeValue();
}
}
元素如 org.w3c.dom.Element
我猜你的 XML
负载如下所示:
<root>
<parent-element>
<id-00001>value 1</id-00001>
<id-00002>value 2</id-00002>
</parent-element>
</root>
要读取具有动态名称的节点,我们需要编写自定义适配器 (javax.xml.bind.annotation.adapters.XmlAdapter
)。假设模型如下所示:
@XmlRootElement(name = "root")
@XmlAccessorType(XmlAccessType.FIELD)
class Root {
@XmlElement(name = "parent-element")
@XmlJavaTypeAdapter(IdsXmlAdapter.class)
private MultiItemList list;
// getters, setters, toString
}
class MultiItemList {
private List<String> ids;
// getters, setters, toString
}
对于以上 XML
和 POJO
模型自定义适配器可能如下所示:
class IdsXmlAdapter extends XmlAdapter<Object, MultiItemList> {
@Override
public MultiItemList unmarshal(Object v) {
Element element = (Element) v;
NodeList childNodes = element.getChildNodes();
List<String> ids = new ArrayList<>(childNodes.getLength());
for (int i = 0; i < childNodes.getLength(); i++) {
Node item = childNodes.item(i);
if (item.getNodeName().equals("#text")) {
continue;
}
ids.add(item.getTextContent());
}
MultiItemList multiItemList = new MultiItemList();
multiItemList.setIds(ids);
return multiItemList;
}
@Override
public Object marshal(MultiItemList v) throws Exception {
return null; // Implement if needed
}
}
用法示例:
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import javax.xml.bind.JAXBContext;
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.adapters.XmlAdapter;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;
public class JaxbApp {
public static void main(String[] args) throws Exception {
File xmlFile = new File("./resource/test.xml").getAbsoluteFile();
JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
Object unmarshal = jaxbContext.createUnmarshaller().unmarshal(new FileReader(xmlFile));
System.out.println(unmarshal);
}
}
打印:
Root{list=Root{ids=[value 1, value 2]}}
注意,您不能直接实施 XmlAdapter<Element, MultiItemList>
适配器,因为异常:
Exception in thread "main" com.sun.xml.internal.bind.v2.runtime.IllegalAnnotationsException: 1 counts of IllegalAnnotationExceptions
org.w3c.dom.Element is an interface, and JAXB can't handle interfaces.
this problem is related to the following location:
at org.w3c.dom.Element
另请参阅: