抱歉长帖,提前感谢!
<RootTag>
<Container type="type1">
<value name="name1"/>
<value name="name2"/>
</Container>
<Container type="type2">
<value name="name3"/>
<value name="name4"/>
</Container>
</RootTag>
在我的JAXB中(代码如下),我有一组值集,其中内部集被包装成一个容器类。所以,我有一组值容器,其中一个值是一个泛型类。问题:除非选择的泛型类是硬编码的,否则值不会得到解析。
关于XML的说明:
>
只应该有两
个
包装所有这些,我们有一个包含
Set的Root类
java.lang.ClassCastException: com.sun.org.apache.xerces.internal.dom.ElementNSImpl cannot be cast to ElementName
在Container类中,我指定了
的标签名称
@XmlElement(name = "value")
如果我只是在这里对类型进行硬编码,如下所示:
@XmlElement(name = "value", type = ElementName.class)
然后JAXB正确解析标记。但是,正如我所说,这个类应该是通用的,所以这对我来说不是一个真正的解决方案。
根
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/*
* <RootTag>
* *
* </RootTag>
*/
@XmlRootElement(name = "RootTag")
public class Root {
/* <Container type = "type1">
* <value name = "name1"/>
* <value name = "name2"/>
* </Container>
* <Container type = "type2">
* <value name = "name3"/>
* <value name = "name4"/>
* </Container>
*/
@XmlElement(name = "Container")
private Set<Container<ElementName>> containers;
// for each of the two Container types
// we create a set of its corresponding values' names
// and then we null the containers field
@XmlTransient
private Map<String, Set<String>> valuesNames = new HashMap<>(2);
//Basically that is @PostConstruct, but works with JAXB
void afterUnmarshal(Unmarshaller u, Object parent) {
containers.forEach(container -> valuesNames.put(container.getType(),
container.getValues().stream()
.map(ElementName::getName)
.collect(Collectors.toSet())));
containers = null;
}
/** return unique value names from both container types */
public Set<String> getAllValuesNames() {
return valuesNames.values().stream()
.flatMap(Set::stream)
.collect(Collectors.toSet());
}
}
容器
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.*;
import java.util.Set;
/*
* <* type = "type1">
* <value *>*
* <value *>*
* </*>
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Container<T> {
@XmlAttribute
private String type;
@XmlElement(name = "value")
private Set<T> values;
public String getType() {
return type;
}
public Set<T> getValues() {
return values;
}
}
元素名称
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
/*
* <* name = "name2"/>
*/
@XmlAccessorType(XmlAccessType.FIELD)
public class ElementName {
@XmlAttribute
private String name;
public String getName() {
return name;
}
}
public static void main(String[] args) throws JAXBException {
final String xmlSerialized = "<RootTag>\n" +
" \n" +
" <Container type=\"type1\">\n" +
" <value name=\"name1\"/>\n" +
" <value name=\"name2\"/>\n" +
" </Container>\n" +
" \n" +
" <Container type=\"type2\">\n" +
" <value name=\"name3\"/>\n" +
" <value name=\"name4\"/>\n" +
" </Container>\n" +
" \n" +
"</RootTag>";
System.out.println("XML:\n" +
"=======================================\n" +
xmlSerialized +
"\n=======================================");
//works just the same with only Root.class
JAXBContext context = JAXBContext.newInstance(Root.class, Container.class, ElementName.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
Root xmlDeserialized = (Root) unmarshaller.unmarshal(new StringReader(xmlSerialized));
System.out.println("Values' names: " + xmlDeserialized.getAllMetricNames());
}
如果一切正常(如果我在Container类的注释中硬编码ElementName.class),它会给出以下输出:
XML:
=======================================
<RootTag>
<Body>
<Container type="type1">
<value name="name1"/>
<value name="name2"/>
</Container>
<Container type="type2">
<value name="name3"/>
<value name="name4"/>
</Container>
</Body>
</RootTag>
=======================================
Values' names: [name4, name3, name2, name1]
用JAXB解组通用列表。
>
主要思想是代替使用
List
之前:
@XmlElement(name = "value")
private Set<T> values;
之后:
@XmlAnyElement(lax = true)
private Set<T> values;
再次运行(
JAXBContext.newInstance(Root.class,Container.class,ElementName.class)
):没有任何变化,值仍然是ElementNSImpl
类型。此外,我不喜欢我允许标记的任何名称,它必须是“值”。
间歇性类广播在取消编组期间从元素NS到自己的类型
在他们的案例中,问题是他们创建了
JAXBContext
而没有提供一些所需的类。不适用于我。
JAXB解组XML类转换异常
在他们的例子中,问题是Java类型擦除,这意味着Java在编译时确定泛型类型,然后编译代码,然后从泛型中删除类型,所以JVM不知道这些泛型类型是什么。我敢打赌这是我的情况,但我不知道如何检查或修复它。
匿名用户
我找到解决办法了!我使用了Blaise Doughan在这里描述的方法,这是< code>XmlAdapter类的用法。我将一组值转换为一组字符串,将< code>ElementName改编为< code>String。然后是要映射的容器。
附言。我像在我的另一个答案中一样保留了ContainerOfElementName
。这是重复的代码,但似乎没有更好的方法来创建JAXB层次结构。
p、 p.s.问题是Java类型擦除(IMHO)<代码>设置
当前解决方法-非常欢迎其他答案
我在对泛型类型进行硬编码时利用了一点这个想法——我将Container类拆分为两个类和
容器
import javax.xml.bind.annotation.*;
import java.util.Set;
/*
* <Container type = "type1">
* *
* </Container>
*/
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public abstract class Container {
@XmlAttribute
private String type;
public String getType() {
return type;
}
/** Derived classes will declare the generic type for us. */
public abstract Set<?> getValues();
}
元素名称的容器
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import java.util.Set;
import java.util.stream.Collectors;
/*
* <Container type = "type1">
* <value name="name1"/>
* <value name="name2"/>
* </Container>
*/
public class ContainerOfElementName extends Container {
@XmlElement(name = "value")
private Set<ElementName> values;
@Override
public Set<ElementName> getValues() {
return values;
}
public Set<String> getNames() {
return values.stream().map(v -> v.name).collect(Collectors.toSet());
}
/*
* <* name = "name2"/>
*/
@XmlAccessorType(XmlAccessType.FIELD)
public static class ElementName {
@XmlAttribute
private String name;
}
}
现在在Root类中:
@XmlElement(name = "Container")
private Set<ContainerOfElementName> containers;
void afterUnmarshal(Unmarshaller u, Object parent) {
containers.forEach(container -> valuesNames.put(container.getType(),
container.getNames()));
containers = null;
}
这有效,但它迫使我为每个可能的类创建容器的子类,该类表示
问题内容: 我如何指示JAXB处理此问题? XML格式 根java 这不起作用… allChildren为空。 问题答案: 您可以更改模型并执行以下操作: 根 父母 更新 有可能避免上课吗? 有两种不同的方法可以完成此操作: 选项#1-使用XmlAdapter的任何JAXB实现 您可以使用XmlAdapter虚拟添加类。 子适配器 根 该注释被用于引用。 儿童 选项#2-使用EclipseLink
我目前正在学习如何在android中使用Jaxb解析xml文件。但是我不知道代码中有什么错误,以及在哪里和如何纠正它。我无法解析xml并获得食品列表。如果我删除List并简单地把它写成Food,那么只有xml中的最后一个元素被解析,其余的似乎都被覆盖了。请帮助我。 我试图解析http://www.w3schools.com/xml/simple.xml,,目前我有这样的代码: ---- 用于取消
问题内容: 我正在尝试创建一个非常简单的REST服务器。我只是有一个测试方法,它将返回字符串列表。这是代码: 它给出以下错误: 我希望JAXB对诸如String,Integer等简单类型具有默认设置。我想不是。这是我的想象: 使这种方法最简单的方法是什么? 问题答案: 我使用@LiorH的示例并将其扩展为: 注意,它使用泛型,因此您可以将其与String之外的其他类一起使用。现在,应用程序代码很简
如有任何线索将不胜感激。谢谢,约翰 XML是巨大的,但这里有一个片段,序列中的媒体是空的,而它不应该是空的。
我试图让Maven使用嵌套的xml模式生成JAXB绑定:模式a导入模式B。模式B导入模式C。 如果模式A中的对象引用了模式B中不依赖于模式C对象的对象,那么一切都构建得很好。如果模式B中的对象引用了模式C中的对象,它就会中断。也就是说,深入一层是可行的。去两个深度没有。 只要我在模式A中添加一个引用模式B中对象的对象,而模式B又引用了模式C中的对象,我就会得到一个组织。xml。萨克斯。SAXPar
与marshall和unmarshall的读者和作者有争议。就是这样。这就是我如何向版画作者写东西的方式。 我是这样得到它的: 然后此解组操作将挂起。它没有给我任何东西,甚至没有例外。