我正在尝试将以下“attrName”和“attrType”XML-Elements编组并解组为单个类。 (目前我单独读取值并在Java中解组后构造我的对象。)
<wrapper>
<someOtherElement>xxx</someOtherElement>
<attrName ref="a">xxx</attrName>
<attrName ref="b">xxx</attrName>
<attrName ref="c">xxx</attrName>
<attrType attrRef="a">xxx</attrType>
<attrType attrRef="b">xxx</attrType>
<someOtherElement>xxx</someOtherElement>
</wrapper>
“ref”XML-Attribute用于标识属性,并用作“attrType”XML-Element的引用。但是“attrType”XML-Element是可选的,不能存在。没有“attrName”XML元素的“attrType”XML元素。
我需要生成类的“属性”对象列表:
package example;
public class Attribute {
private String name;
private String ref;
private String type;
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref= ref;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type= type;
}
}
我已经找到以下关于question的内容。但它并没有帮助我找到解决问题的方法。 问题是找到所有相关的属性名称和类型来构造Java对象。
我会对正确方向的任何提示或建议表示感谢。如果我没有解释任何令人满意的事情,请不要犹豫,因为英语不是我的母语。
PS:我知道我可以使用不同的XML结构并轻松解决问题。但这对我来说是不可能的。
答案 0 :(得分:0)
您的XML文件不遵循任何架构,因此您只能依赖其根元素名称以及格式正确的事实。下面将它映射到通用Wrapper对象,然后处理它以生成Attribute对象列表:
public class JAXBAttribute {
public static void main(String[] args) throws JAXBException {
JAXBContext context = JAXBContext.newInstance(new Class[] {Wrapper.class});
Wrapper wrapper = (Wrapper)context.createUnmarshaller().unmarshal(Thread.currentThread().getContextClassLoader().getResourceAsStream("wrapper.xml"));
final Map<String,String> attributeTypeMap = new HashMap<String,String>();
for(final AttributeTypeMapEntry entry : wrapper.getEntryList()) {
attributeTypeMap.put(entry.getKey(), entry.getValue());
}
for(final Attribute a : wrapper.getAttributeObjectList()) {
a.setType(attributeTypeMap.get(a.getRef()));
}
System.out.println(wrapper.getAttributeObjectList());
}
}
@XmlRootElement(name="wrapper")
@XmlAccessorType(XmlAccessType.NONE)
class Wrapper {
@XmlElement(name="attrName")
private List<Attribute> attributeObjectList;
@XmlElement(name="attrType")
private List<AttributeTypeMapEntry> entryList;
public List<Attribute> getAttributeObjectList() {
return attributeObjectList;
}
public List<AttributeTypeMapEntry> getEntryList() {
return entryList;
}
}
@XmlAccessorType(XmlAccessType.NONE) // Only annotated fields will be mapped
class AttributeTypeMapEntry {
@XmlAttribute(name="attrRef")
private String key;
@XmlValue
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "AttributeTypeMapEntry [key=" + key + ", value=" + value + "]";
}
}
@XmlAccessorType(XmlAccessType.NONE) // Only annotated fields will be mapped
class Attribute {
@XmlValue
private String name;
private String type;
@XmlAttribute(name="ref")
private String ref;
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref= ref;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type= type;
}
@Override
public String toString() {
return "Attribute [name=" + name + ", type=" + type + ", ref=" + ref + "]";
}
}
答案 1 :(得分:0)
这是同一任务的另一种解决方案。我们的想法是将初始文档转换为直接映射XML格式,同时解析所有引用,然后将生成的XML映射到Java对象。
您的数据的XSLT将是:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/wrapper">
<xsl:variable name="root" select="."/>
<xsl:copy>
<xsl:for-each select="attrName">
<xsl:variable name="ref" select="@ref"></xsl:variable>
<attribute>
<name><xsl:value-of select="text()"/></name>
<ref><xsl:value-of select="$ref"/></ref>
<type><xsl:value-of select="$root/attrType[@attrRef=$ref]/text()"/></type>
</attribute>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
直接映射XML看起来像:
<?xml version="1.0" encoding="utf-8"?>
<wrapper>
<attribute>
<name>xxx</name>
<ref>a</ref>
<type>xxx</type>
</attribute>
<attribute>
<name>xxx</name>
<ref>b</ref>
<type>xxx</type>
</attribute>
<attribute>
<name>xxx</name>
<ref>c</ref>
<type/>
</attribute>
</wrapper>
带注释的代码如下:
public class JAXBAttribute {
public static void main(String[] args) throws Exception {
// Transform initial XML resolving all references, resulting in an straight-to-map XML
final Transformer t = TransformerFactory.newInstance().newTransformer(
new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("wrapper.xsl")));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
t.transform(
new StreamSource(Thread.currentThread().getContextClassLoader().getResourceAsStream("wrapper.xml")),
new StreamResult(baos));
// Create Java objects from a straight-to-map XML
JAXBContext context = JAXBContext.newInstance(new Class[] {Wrapper.class});
Wrapper wrapper = (Wrapper)context.createUnmarshaller().unmarshal(new ByteArrayInputStream(baos.toByteArray()));
//
System.out.println(wrapper.getAttributeObjectList());
}
}
@XmlRootElement(name="wrapper")
@XmlAccessorType(XmlAccessType.FIELD)
class Wrapper {
@XmlElement(name="attribute")
private List<Attribute> attributeObjectList;
public List<Attribute> getAttributeObjectList() {
return attributeObjectList;
}
}
@XmlAccessorType(XmlAccessType.FIELD)
class Attribute {
private String name;
private String type;
private String ref;
public String getName() {
return name;
}
public void setName(String name) {
this.name= name;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref= ref;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type= type;
}
@Override
public String toString() {
return "Attribute [name=" + name + ", type=" + type + ", ref=" + ref + "]";
}
}
注意此示例的所有文件都保存在类路径根目录中。