Использование JAXB для извлечения внутреннего текста элемента XML
проблема
Учитывая следующий файл конфигурации XML:
<main>
<name>JET</name>
<maxInstances>5</maxInstances>
<parameters>
<a>1</a>
<b>
<b1>test1</b1>
<b2>test2</b2>
</b>
</parameters>
</main>
Мне нужно извлечь значение элементов name и maxInstances, а затем весь внутренний текст элемента параметров. например
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;
Нужно ли переключаться на другой стиль парсера? Это хорошая / плохая идея использовать два стиля парсера?
2 ответа
Самое близкое, что вы можете придумать, - это сопоставить "параметры" с деревом DOM, объявив переменную как org.w3c.dom.Node
, (На самом деле, объявив JAXBElement).
Для получения дополнительной информации см. http://jaxb.java.net/guide/Avoid_strong_databinding.html. Это дает вам рецепт в первую очередь для схемы, вы можете увидеть, как начать с Java, запустив эту схему через xsd2java и посмотрев на результат.
Чтобы получить строку, вам нужно сериализовать из DOM.
Или, более конкретно:
эта страница здесь описывает xsd: любую обработку, и, таким образом,
@XmlAnyElement
public List<Element> getParameters();
куда Element
это интерфейс DOM
Вы можете использовать @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;
}
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);
}
}
}
демонстрация
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);
}
}