使用 JAXB 提取 XML 元素的内部文本

发布于 2024-10-30 04:06:18 字数 1417 浏览 6 评论 0原文

问题

给定以下 XML 配置文件:

<main>
  <name>JET</name>
  <maxInstances>5</maxInstances>
  <parameters>
    <a>1</a>
    <b>
      <b1>test1</b1>
      <b2>test2</b2>
    </b>
  </parameters>
</main>

我需要提取 name 和 maxInstances 元素的值,然后提取parameters 元素的整个内部文本。例如

name = "JET"
maxInstances = 5
parameters = "<a>1</a><b><b1>test1</b1><b2>test2</b2></b>"

,最终参数块可以包含任何格式良好的XML。

尝试的解决方案

以下代码适用于 name 和 maxInstances,但不适用于参数:

@XmlRootElement(name="main")
public class Main {

    @XmlElement(name="name", required="true")
    private String name;

    @XmlElement(name="maxInstances", required="true")
    private Integer maxInstances;

    @XmlElement(name="parameters")
    private String parameters;

}

我尝试根据以下想法寻找解决方案,但找不到合适的解决方案。

是否可以使用不同的类型来表示可以解析以生成字符串的 XML 树的参数对象?例如

@XmlElement(name="parameters")
private XmlNodeObject parametersNode;

public String getParameters() {
    // Collapse node to single line of text
    return innerText;
}

或者我需要使用某种不同类型的注释吗?

@XmlSpecialAnnotation(...)
@XmlElement(name="parameters")
private String parameters;

我需要切换到不同风格的解析器吗?使用两种风格的解析器是好还是坏主意?

Problem

Given the following XML configuration file:

<main>
  <name>JET</name>
  <maxInstances>5</maxInstances>
  <parameters>
    <a>1</a>
    <b>
      <b1>test1</b1>
      <b2>test2</b2>
    </b>
  </parameters>
</main>

I need to extract the value of the name and maxInstances elements and then the whole inner text of the parameters element. e.g.

name = "JET"
maxInstances = 5
parameters = "<a>1</a><b><b1>test1</b1><b2>test2</b2></b>"

Ultimately the parameters block can contain any well formed XML.

Attempted Solution

The following code works for name and maxInstances but not parameters:

@XmlRootElement(name="main")
public class Main {

    @XmlElement(name="name", required="true")
    private String name;

    @XmlElement(name="maxInstances", required="true")
    private Integer maxInstances;

    @XmlElement(name="parameters")
    private String parameters;

}

I've tried looking at solutions based on the following ideas but can't find something appropriate.

Is there a different type I can use for the parameters object representing the XML Tree that I could parse to produce a string? e.g.

@XmlElement(name="parameters")
private XmlNodeObject parametersNode;

public String getParameters() {
    // Collapse node to single line of text
    return innerText;
}

Or do I need to use some different kind of annotation?

@XmlSpecialAnnotation(...)
@XmlElement(name="parameters")
private String parameters;

Do I need to switch to a different style of parser? Is it a good/bad idea to use two styles of parser?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蒗幽 2024-11-06 04:06:18

您可以使用 @XmlAnyElement 注释 如 bmargulies 所描述。要映射到问题中的对象模型,您可以利用 DOMHandler

主要

import javax.xml.bind.annotation.*;

@XmlRootElement(name="main")
@XmlAccessorType(XmlAccessType.FIELD)
public class Main {

    private String name;

    private Integer maxInstances;

    @XmlAnyElement(value=ParameterHandler.class)
    private String parameters;

}

参数处理程序

import java.io.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.*;

public class ParameterHandler implements DomHandler<String, StreamResult> {

    private static final String PARAMETERS_START_TAG = "<parameters>";
    private static final String PARAMETERS_END_TAG = "</parameters>";
    private StringWriter xmlWriter = new StringWriter(); 

    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
        return new StreamResult(xmlWriter);
    }

    public String getElement(StreamResult rt) {
        String xml = rt.getWriter().toString();
        int beginIndex = xml.indexOf(PARAMETERS_START_TAG) + PARAMETERS_START_TAG.length();
        int endIndex = xml.indexOf(PARAMETERS_END_TAG);
        return xml.substring(beginIndex, endIndex);
    }

    public Source marshal(String n, ValidationEventHandler errorHandler) {
        try {
            String xml = PARAMETERS_START_TAG + n.trim() + PARAMETERS_END_TAG;
            StringReader xmlReader = new StringReader(xml);
            return new StreamSource(xmlReader);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

演示

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception  {
        JAXBContext jc = JAXBContext.newInstance(Main.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Main main = (Main) unmarshaller.unmarshal(new File("input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(main, System.out);
    }

}

You can use the @XmlAnyElement annotation as described by bmargulies. To map to the object model in your question you can leverage a DOMHandler.

Main

import javax.xml.bind.annotation.*;

@XmlRootElement(name="main")
@XmlAccessorType(XmlAccessType.FIELD)
public class Main {

    private String name;

    private Integer maxInstances;

    @XmlAnyElement(value=ParameterHandler.class)
    private String parameters;

}

ParameterHandler

import java.io.*;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.annotation.DomHandler;
import javax.xml.transform.Source;
import javax.xml.transform.stream.*;

public class ParameterHandler implements DomHandler<String, StreamResult> {

    private static final String PARAMETERS_START_TAG = "<parameters>";
    private static final String PARAMETERS_END_TAG = "</parameters>";
    private StringWriter xmlWriter = new StringWriter(); 

    public StreamResult createUnmarshaller(ValidationEventHandler errorHandler) {
        return new StreamResult(xmlWriter);
    }

    public String getElement(StreamResult rt) {
        String xml = rt.getWriter().toString();
        int beginIndex = xml.indexOf(PARAMETERS_START_TAG) + PARAMETERS_START_TAG.length();
        int endIndex = xml.indexOf(PARAMETERS_END_TAG);
        return xml.substring(beginIndex, endIndex);
    }

    public Source marshal(String n, ValidationEventHandler errorHandler) {
        try {
            String xml = PARAMETERS_START_TAG + n.trim() + PARAMETERS_END_TAG;
            StringReader xmlReader = new StringReader(xml);
            return new StreamSource(xmlReader);
        } catch(Exception e) {
            throw new RuntimeException(e);
        }
    }

}

Demo

import java.io.File;
import javax.xml.bind.*;

public class Demo {

    public static void main(String[] args) throws Exception  {
        JAXBContext jc = JAXBContext.newInstance(Main.class);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        Main main = (Main) unmarshaller.unmarshal(new File("input.xml"));

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(main, System.out);
    }

}
遗忘曾经 2024-11-06 04:06:18

最接近的方法是将“参数”映射到 DOM 树,方法是将变量声明为 org.w3c.dom.Node。 (实际上,声明一个 JAXBElement)。

有关详细信息,请参阅 http://jaxb.java.net/guide/Avoid_strong_databinding.html 。这为您提供了模式优先的处方,您可以通过 xsd2java 运行该模式并查看输出来了解如何从 java 开始。

要获取字符串,您必须从 DOM 进行序列化。

或者,更具体地说:

此页面这里描述了xsd:any处理,因此

  @XmlAnyElement
  public List<Element> getParameters();

其中Element是DOM接口。

The closest you could come is to map 'parameters' to a DOM tree, by declaring the variable to be org.w3c.dom.Node. (Actually, declaring a JAXBElement).

For details, see http://jaxb.java.net/guide/Avoid_strong_databinding.html. That gives you the schema-first prescription, you can see how to start from java by running that schema through xsd2java and looking at the output.

To get a string you'll have to serialize from the DOM.

Or, even more specifically:

this page here describes xsd:any processing, and thus

  @XmlAnyElement
  public List<Element> getParameters();

Where Element is the DOM interface.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文