简单 XML 反序列化具有相同名称的不同元素类型
Simple XML deserializing different element types with the same name
我正在尝试反序列化 Java 中 XML 的这个片段:
<anime id="16986">
<info type="Picture" src="http://~.jpg" width="141" height="200">
<img src="http://~" width="141" height="200"/>
<img src="http://~" width="318" height="450"/>
</info>
<info type="Main title" lang="EN">Long Riders!</info>
<info type="Alternative title" lang="JA">ろんぐらいだぁす!</info>
</anime>
我 运行 遇到的问题是 info
元素可以有一个 img
的内联列表,也可以只包含文本。我正在考虑在我的 AnimeHolder class 中将 info
视为 @Element
,但我不能有重复的注释。我还想访问 info 的 lang
属性来检查它是 EN 还是 JP。
我正在使用这些 classes 来保存反序列化数据:
@Root(name="anime", strict=false)
public class AnimeHolder {
@Attribute(name="id")
private String ANNID;
@ElementList(inline=true)
private List<InfoHolder> infoList;
public String getANNID() {
return ANNID;
}
public List<InfoHolder> getInfoList() {
return infoList;
}
}
对于信息项:
@Root(name="info", strict = false)
public class InfoHolder {
@ElementList(inline=true, required = false)
private List<ImgHolder> imgList;
@Attribute(name = "lang", required = false)
private String language;
public List<ImgHolder> getImgList() {
return imgList;
}
}
通过 Andreas,我发现我需要研究处理混合内容。做一些搜索让我找到这个 solution about creating a custom Converter
. After writing my own and finding out it wasn't being called, this 帮助解决了这个问题。这是我重新制作的 InfoHolder
class 和转换器:
@Root(name="info", strict = false)
@Convert(InfoHolder.InfoConverter.class)
public class InfoHolder {
private String englishTitle;
private String imageURL;
static class InfoConverter implements Converter<InfoHolder> {
@Override
public InfoHolder read(InputNode node) throws Exception {
String value = node.getValue();
InfoHolder infoHolder = new InfoHolder();
if (value == null){
InputNode nextNode = node.getNext();
while (nextNode != null){
String tag = nextNode.getName();
if (tag.equals("img") && nextNode.getAttribute("src") != null){
infoHolder.imageURL = nextNode.getAttribute("src").getValue();
}
nextNode= node.getNext();
}
} else {
while (node != null){
if (node.getAttribute("lang") != null){
if (node.getAttribute("lang").getValue().equals("EN")){
infoHolder.englishTitle = value;
break;
}
}
node = node.getNext();
}
}
return infoHolder;
}
@Override
public void write(OutputNode node, InfoHolder value) throws Exception {
}
}
}
我还需要使用 AnnotationStrategy
实例化 SimpleXmlConverterFactory
和 Serializer
,如下所示:
SimpleXmlConverterFactory factory = SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy()));
使用自定义转换器公开 XML 节点,这使我能够确定 info
节点是否有 img
个子节点,如果没有,则获取节点值本身。
我正在尝试反序列化 Java 中 XML 的这个片段:
<anime id="16986">
<info type="Picture" src="http://~.jpg" width="141" height="200">
<img src="http://~" width="141" height="200"/>
<img src="http://~" width="318" height="450"/>
</info>
<info type="Main title" lang="EN">Long Riders!</info>
<info type="Alternative title" lang="JA">ろんぐらいだぁす!</info>
</anime>
我 运行 遇到的问题是 info
元素可以有一个 img
的内联列表,也可以只包含文本。我正在考虑在我的 AnimeHolder class 中将 info
视为 @Element
,但我不能有重复的注释。我还想访问 info 的 lang
属性来检查它是 EN 还是 JP。
我正在使用这些 classes 来保存反序列化数据:
@Root(name="anime", strict=false)
public class AnimeHolder {
@Attribute(name="id")
private String ANNID;
@ElementList(inline=true)
private List<InfoHolder> infoList;
public String getANNID() {
return ANNID;
}
public List<InfoHolder> getInfoList() {
return infoList;
}
}
对于信息项:
@Root(name="info", strict = false)
public class InfoHolder {
@ElementList(inline=true, required = false)
private List<ImgHolder> imgList;
@Attribute(name = "lang", required = false)
private String language;
public List<ImgHolder> getImgList() {
return imgList;
}
}
通过 Andreas,我发现我需要研究处理混合内容。做一些搜索让我找到这个 solution about creating a custom Converter
. After writing my own and finding out it wasn't being called, this 帮助解决了这个问题。这是我重新制作的 InfoHolder
class 和转换器:
@Root(name="info", strict = false)
@Convert(InfoHolder.InfoConverter.class)
public class InfoHolder {
private String englishTitle;
private String imageURL;
static class InfoConverter implements Converter<InfoHolder> {
@Override
public InfoHolder read(InputNode node) throws Exception {
String value = node.getValue();
InfoHolder infoHolder = new InfoHolder();
if (value == null){
InputNode nextNode = node.getNext();
while (nextNode != null){
String tag = nextNode.getName();
if (tag.equals("img") && nextNode.getAttribute("src") != null){
infoHolder.imageURL = nextNode.getAttribute("src").getValue();
}
nextNode= node.getNext();
}
} else {
while (node != null){
if (node.getAttribute("lang") != null){
if (node.getAttribute("lang").getValue().equals("EN")){
infoHolder.englishTitle = value;
break;
}
}
node = node.getNext();
}
}
return infoHolder;
}
@Override
public void write(OutputNode node, InfoHolder value) throws Exception {
}
}
}
我还需要使用 AnnotationStrategy
实例化 SimpleXmlConverterFactory
和 Serializer
,如下所示:
SimpleXmlConverterFactory factory = SimpleXmlConverterFactory.create(new Persister(new AnnotationStrategy()));
使用自定义转换器公开 XML 节点,这使我能够确定 info
节点是否有 img
个子节点,如果没有,则获取节点值本身。