jaxb将多个xml元素封送和解封到一个类中并进行反向

zbwhf8kr  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(284)

我正在尝试将以下“attrname”和“attrtype”xml元素封送和解封到一个类中(目前,我单独读取这些值,并在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属性用于标识属性并作为“attrtype”xml元素的引用。但是“attrtype”xml元素是可选的,不能存在。没有“attrname”xml元素就不能有“attrtype”xml元素。
我需要生成类的“attribute”对象列表:

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;
    }
}

我已经发现了以下相关问题。但这无助于我找到解决问题的办法。问题是找到所有相关的属性名和类型来构造java对象。
如果有任何正确的建议,我将不胜感激。如果我没有解释任何令人满意的事情,请不要犹豫,因为英语不是我的母语。
ps:我知道我可以使用不同的xml结构,很容易解决问题。但这对我来说是不可能的。

3j86kqsm

3j86kqsm1#

您的xml文件不遵循任何模式,因此只能依赖其根元素名称和格式良好的事实。下面将其Map到通用 Package 器对象,然后对其进行处理以生成属性对象列表:

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 + "]";
    }
}
uelo1irk

uelo1irk2#

这是同一任务的另一个解决方案。其思想是将初始文档转换为直接Mapxml形式,同时解析所有引用,然后将生成的xmlMap到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>

直接Mapxml如下所示:

<?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 + "]";
    }
}

注意本例中的所有文件都保存在类路径根目录中。

相关问题