当前位置: 首页 > 知识库问答 >
问题:

JAXB基于像XML-Nodes这样的继承

冯新知
2023-03-14

我是JAXB的新手,所以我不确定我想做的事情是否可能。

我有一个XML文件,基本上是为我的程序配置一些运行参数。某些配置共享大量相同的参数,只有1或2个参数不同。所以我的XML现在看起来像这样:

<Parameters id="1">
    <Attribute1>value1<Attribute1>
    <Attribute2>value2<Attribute2>
    <Attribute3>value3<Attribute3>
    <Attribute4>value4<Attribute4>
    <Attribute5>value5<Attribute5>
</Parameters>

<Parameters id="2">
    <Attribute1>value1<Attribute1>
    <Attribute2>value2<Attribute2>
    <Attribute3>value3<Attribute3>
    <Attribute4>otherValue4<Attribute4>
    <Attribute5>otherValue5<Attribute5>
</Parameters>

我正在寻找一种减少冗余的方法,这样我就有了一个基本配置,然后扩展,在扩展中,我只需要配置不同的参数。

<Parameters id="1">
    <Attribute1>value1<Attribute1>
    <Attribute2>value2<Attribute2>
    <Attribute3>value3<Attribute3>
</Parameters>

<Parameters id="2" parent="1">
    <Attribute4>value4<Attribute4>
    <Attribute5>value5<Attribute5>
</Parameters>

<Parameters id="3" parent="1">
    <Attribute4>otherValue4<Attribute4>
    <Attribute5>otherValue5<Attribute5>
</Parameters>

值得一提的是,父节点的属性集对于不同的配置组不是固定的,也就是说,在其他情况下,属性1可能是正在改变的。JAXB有可能做到这一点吗?

我猜我对问题场景的最初描述有点不清楚/遗漏了一些细节。

我的参数设置是同一个根节点下一个xml文件中的所有单个节点。我使用XPATH检索单个参数节点,并将此节点散集到一个参数对象中。

到目前为止还不错,但是我现在想做的是通过使用某种继承来重组我的xml来减少冗余。例如,当加载id="2"的节点时,我希望我的参数对象继承id="1"的节点的值。

我对这个问题的解决方法分为两个简单的步骤。在第一步中,我只是从XML节点加载对象。然后检查节点是否有指定的parentId。如果是这种情况,我还为父对象加载对象,并将fiedl值复制到子对象(如果尚未设置)。

public static Parameters createParams(String id){
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = builderFactory.newDocumentBuilder();
    Document xmlDocument = builder.parse(new File("src/test.xml"));
    XPath xPath = XPathFactory.newInstance().newXPath();

    JAXBContext jc = JAXBContext.newInstance(Parameters.class);
    Unmarshaller unmarshaller = jc.createUnmarshaller();
    Node n = (Node) xPath.compile("/config/Parameters[@id='"+id+"']").evaluate(xmlDocument, XPathConstants.NODE);
    Parameters p = (Parameters) unmarshaller.unmarshal(n);  

    if(p.parentId != null)
        p.loadValuesFromParent(createParams(p.parentId));

    return p;
}

public void loadValuesFromParent(Parameters parent) throws IllegalArgumentException, IllegalAccessException{
    for (Field field : Parameters.class.getDeclaredFields()) {
        if(field.get(this)==null){
            field.set(this,field.get(parent));
        }
    } 
}

共有1个答案

濮君植
2023-03-14

根据我的评论,这可以通过任何简单的pojo实现,除非问题中缺少一些特别的东西。

样品pojo与主。

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
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 javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement()
@XmlAccessorType(XmlAccessType.FIELD)
public class Parameters {

    @XmlAttribute
    private String id;

    @XmlAttribute
    private String parent;

    @XmlElement(name = "Attribute1")
    private String attribute1;

    @XmlElement(name = "Attribute2")
    private String attribute2;

    @XmlElement(name = "Attribute3")
    private String attribute3;

    @XmlElement(name = "Attribute4")
    private String attribute4;

    @XmlElement(name = "Attribute5")
    private String attribute5;
    public static void main(String[] args) throws Exception{
        JAXBContext jc = JAXBContext.newInstance(Parameters.class);
        Marshaller marrshaller = jc.createMarshaller();
        marrshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
        Parameters p1 = new Parameters();
        p1.id="1";
        p1.attribute1="value1";
        p1.attribute2="value2";
        p1.attribute3="value3";
        marrshaller.marshal(p1, System.out);

         p1 = new Parameters();
        p1.id="2";
        p1.parent="1";
        p1.attribute4="value4";
        p1.attribute5="value5";
        marrshaller.marshal(p1, System.out);

         p1 = new Parameters();
        p1.id="3";
        p1.parent="1";
        p1.attribute4="Othervalue4";
        p1.attribute5="othervalue5";
        marrshaller.marshal(p1, System.out);
    }
}

和三个xml输出:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parameters id="1">
    <Attribute1>value1</Attribute1>
    <Attribute2>value2</Attribute2>
    <Attribute3>value3</Attribute3>
</parameters>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parameters parent="1" id="2">
    <Attribute4>value4</Attribute4>
    <Attribute5>value5</Attribute5>
</parameters>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<parameters parent="1" id="3">
    <Attribute4>Othervalue4</Attribute4>
    <Attribute5>othervalue5</Attribute5>
</parameters>
 类似资料:
  • 我目前正在尝试使用JaxB,但对于一个相对简单的示例,我并不是很成功。我的示例如下: 我所有的尝试(甚至编组)都失败了。我浏览了BlaiseDoughan的博客,包括http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html但他们似乎对我的例子都没有帮助。我很可能误用了他的例子。在我看来,我的示例应该是JaxB中

  • 问题内容: 在JavaScript中,每个对象同时是一个实例和一个类。要进行继承,可以将任何对象实例用作原型。 在Python,C ++等中,有类和实例作为单独的概念。为了进行继承,您必须使用基类创建一个新类,然后可以使用该新类来生成派生实例。 为什么JavaScript朝这个方向发展(基于原型的面向对象)?与传统的基于类的OO相比,基于原型的OO有哪些优点和缺点? 问题答案: 这里大约有一百个术

  • 问题内容: 我有一个自定义返回的我想将它作为任意XML包含在JAXB对象中(我知道我必须手工制作XSD)。但是,JAXB抱怨 显然,不支持将w3c XML类型作为Java类型来支持,这很遗憾。但是,除此之外,使用明显受到支持的错误时,我会遇到相同的错误。 如何在JAXB中包括任意XML元素作为元素? 注意:根据https://forums.oracle.com/thread/1668210我也尝试

  • 问题内容: 我有两节课: 我想将类B编组为xml元素,并添加类A的属性fieldOfClassB和fieldOfClassA,但在编组期间会显示以下警告消息: 请注意,这两个类来自两个不同的程序包,我无法更改此对象模型。 先感谢您! 编辑: 我正在使用外部绑定文件。 问题答案: 从您发布的日志消息中,我可以看到您正在使用MOXy的外部映射文档(请参阅http://blog.bdoughan.com

  • 要使用本节中描述的AOP命名空间标记,您需要按照描述导入springAOP模式 - <?xml version = "1.0" encoding = "UTF-8"?> <beans xmlns = "http://www.springframework.org/schema/beans" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-insta

  • 问题内容: 是否可以使用JAXB根据xml的属性将xml解组到特定的Java类? 我想要一个包含三角形和正方形的Shape对象的列表,每个对象都有自己的特定于形状的属性。IE浏览器: 我目前只是将所有属性都放在一个大的“ Shape”类中,这并不理想。 如果形状已正确命名为xml元素,则可以使它正常工作,但是不幸的是,我无法控制要检索的xml。 谢谢! 问题答案: JAXB是一个规范,特定的实现将