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

如何使用JAX-B从XML中读取所选类的对象(多态)

颜君浩
2023-03-14

我创建了一个多态对象列表。我可以将它们转换为XML,反之亦然(使用JAXB编组和反编组),但我只想读取所选类中的对象。

我使用了一些关于通过JAXB转换对象列表的教程,例如这个:http://memorynotfound.com/convert-xml-to-polymorphic-object-using-jax-b/或这个:http://bdoughan.blogspot.com/2010/11/jaxb-and-inheritance-using-substitution.html我有动物列表,以及两个扩展抽象动物类的类,狗、猫和鸟。我将该列表(包含狗和猫)保存为XML,我想从XML文件中只获取猫。可以制作吗?

使用教程中的代码-

    JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
    Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();

    Root root = (Root)unmarshaller.unmarshal(new StringReader(xml));

我会得到输出:

根{动物=[com.memorynotfound.xml.jaxb.Dog@520a3426, com.memorynotfound.xml.jaxb.Cat@18eed359,com.memorynotfound.xml.jaxb.Bird@643bd123]}

我努力实现的是:

根{动物=[com.memorynotfound.xml.jaxb.Cat@18eed359]}

在一个回答中,我想到了XMLEvent。这是一个非常好的想法,但是几乎每个教程都提到了过滤。我想实现的是摆脱所有其他类。我试着改变代码:

public XMLEvent nextEvent() throws XMLStreamException {
    // Read next event
    XMLEvent e = super.nextEvent();
    // If it's a start element for dog
    if (e.getEventType() == XMLEvent.START_ELEMENT &&  ("Cat".equals(e.asStartElement().getName().getLocalPart()) ||
            "Bird".equals(e.asStartElement().getName().getLocalPart()))
    )
    {

        // Then run through events until a closing dog event
        do {
            e = super.nextEvent();
        } while (e.getEventType() != XMLEvent.END_ELEMENT || ! ("Cat".equals(e.asStartElement().getName().getLocalPart()) ||
                "Bird".equals(e.asStartElement().getName().getLocalPart()))

        );
        // then read next event after the  ends
        e = super.nextEvent();
    }
    return e;
}

但它不起作用,所以我不确定我是否理解解决方案。

共有2个答案

刘博文
2023-03-14

由于在Root类中,动物同时将狗和猫作为元素,如果可用,它会尝试将其列表到这两个对象中。

实现您想要的一种方法是移除XmlElementWrapper下的一个元素。

  @XmlElementWrapper(name = "animals")
  @XmlElements({
    @XmlElement(name = "cat", type = Cat.class)
  })
  public void setAnimals(List<Animal> animals) {
    this.animals = animals;
  }

以上将为您提供:

Root{animals=[ com.memorynotfound.xml.jaxb.Cat@18eed359]}
林劲
2023-03-14

您可以创建自定义javax.xml.stream.XMLEventReader并过滤一些事件。这是一个愚蠢但有效的示例:

public final class FilteredXmlEventReader extends EventReaderDelegate {

    final Set<String> filteredElements;

    FilteredXmlEventReader(XMLEventReader delegate, String... filteredElements) {
        super(delegate);
        this.filteredElements = new HashSet<String>(Arrays.asList(filteredElements));
    }

    public XMLEvent nextEvent() throws XMLStreamException {
        // Read next event

        XMLEvent e = super.nextEvent();
        // If it's a start element for any filtered
        if (e.getEventType() == XMLEvent.START_ELEMENT && filteredElements.contains(e.asStartElement().getName().getLocalPart())) {
            String element = e.asStartElement().getName().getLocalPart();
            // Then run through events until a closing similar element
            do {
                e = super.nextEvent();
            } while (e.getEventType() != XMLEvent.END_ELEMENT || !element.equals(e.asEndElement().getName().getLocalPart()));
            // then read next tag after closing element
            e = super.nextEvent();
        }
        return e;
    }
}

然后使用以下XMLEventReader解组内容:

JAXBContext jaxbContext = JAXBContext.newInstance(Root.class);
XMLEventReader xmlReader = XMLInputFactory.newFactory().createXMLEventReader(new StringReader(xml));
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
Root root = (Root) unmarshaller.unmarshal(new FilteredXmlEventReader(xmlReader, "Dog", "Bird"));

则不会读取< code>Dog和< code>Birds元素。

请注意,如果多个过滤元素嵌套在此实现中,可能会出现问题。

编辑:编辑了上面的代码以支持多个过滤元素

 类似资料:
  • 我正在编写一个API控制器,用于接收和解析JSON异步帖子的内容,但无法读取该帖子中StringContent对象的内容。 这是我的API控制器中我希望看到值的部分。到达ApiController方法的值为null。jsonContent值是一个空字符串。我希望看到的是JSON对象的内容。 这是我的控制器来显示它是如何被调用的。 这就是发布方法。 我怀疑ApiController中Post方法的签

  • 我正在使用BufferedReader类读取Java程序中的输入。我想从一个用户那里读取输入,这个用户可以在一行空格中输入多个整数数据。我想读取整数数组中的所有这些数据。 输入格式-用户首先输入他/她想要输入的数字 然后在下一行中输入多个整数值- 输入: 5. 2 456 43 21 12 现在,我使用BufferedReader的对象(br)读取输入 接下来,我想读取数组中的下一行输入 但是我们

  • 我在Netbeans构建了一个Java项目。我有一个表单,表单内部有一个jList,其中填充了一个对象(Favorite)。我也有一个按钮,我想当我按下按钮删除选定的项目在jList。 我正在尝试以下代码,但我得到一个错误。 我得到以下错误: 线程“AWT-EventQueue-0”中出现异常Java . lang . classcastexception:Java . lang . string

  • 问题内容: 我需要阅读Java包中包含的类。这些类在类路径中。我需要直接从Java程序执行此任务。你知道简单的方法吗? 问题答案: 如果你的类路径中包含Spring,则可以执行以下操作。 在包中找到所有用XmlRootElement注释的类:

  • 问题内容: 因此,给定对象的JSON数组: 我想从nested中提取键/值的子集,同时保持外部对象的其他属性不变,产生如下结果: 即删除除和以外的所有键。 我确信必须有一种使用jq实现此目标的合理简便的方法。帮助表示赞赏。 问题答案: 您可以使用以下过滤器: 这会映射数组中过滤对象的每个项目,仅包括和属性。

  • 在我的程序的先前代码中,我使用 ObjectOutputStream 和 FileOutPutStream 将一个 ArrayList(由名为 location 的自定义类的对象组成,如您在代码中看到的那样)。但是,当尝试使用 ObjectInputStream 从文件中检索对象时,我收到一条错误消息,指出我有一个未处理的异常(ClassNotFoundException)。 以下是我用来从文件中