这是我的课程:
@XmlRootElement(name = "XmlParent")
public class Foo {
private String name;
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
和我的样本xml文件如下
<XmlParent>
<name>koraytugay</name>
</XmlParent>
目前,我可以使用以下代码从此文件创建对象:
JAXBContext jaxbContext = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
final FileReader fileReader = new FileReader(file);
final Foo foo = (Foo) unmarshaller.unmarshal(fileReader);
// foo.getName() will be koraytugay which is fine..
但是,我想要做的是能够解组以下xml文件:
<XmlParent>
<name>koraytugay</name>
<bar>
<baz>
<qux>00000001</qux>
</baz>
</bar>
</XmlParent>
进入班级:
@XmlRootElement(name = "XmlParent")
public class Foo {
private String name;
private String qux;
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public String getQux() {
return qux;
}
public void setQux(String qux) {
this.qux = qux;
}
}
那我怎么能绕过&#39; bar&#39;和&#39;巴兹&#39;解组时?
答案 0 :(得分:0)
取决于XML的实际结构以及您希望实现的目标。
如果您只需要XML输入中的少量值,那么使用XPath可能是另一种方法。
在下面找一个小片段。
import java.io.ByteArrayInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
...
String in = "<XmlParent>\n"
+ " <name>koraytugay</name>\n"
+ " <bar>\n"
+ " <baz>\n"
+ " <qux>00000001</qux>\n"
+ " </baz>\n"
+ " </bar>\n"
+ "</XmlParent>";
byte[] bytes = in.getBytes();
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document document = builder.parse(new ByteArrayInputStream(bytes));
XPathFactory factory = XPathFactory.newInstance();
XPath xpath = factory.newXPath();
String name = xpath.evaluate("/XmlParent/name", document);
String qux = xpath.evaluate("/XmlParent/bar/baz/qux", document);
System.out.println("name = " + name);
System.out.println("qux = " + qux);
输出
name = koraytugay
qux = 00000001
编辑您可以扩展XMLEventReader
并检查每个事件是否是您要跳过的XML标记。
XML事件阅读器。
import java.util.Set;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
public class FilteringlXmlEventReader implements XMLEventReader {
final XMLEventReader reader;
final Set<QName> qNames;
public FilteringlXmlEventReader(XMLEventReader reader,
Set<QName> qNames) {
this.reader = reader;
this.qNames = qNames;
}
@Override
public XMLEvent nextEvent() throws XMLStreamException {
while (tagToSkip(reader.peek())) {
reader.nextEvent();
}
return reader.nextEvent();
}
// from XMLEventReader
@Override
public boolean hasNext() {
return reader.hasNext();
}
@Override
public XMLEvent peek() throws XMLStreamException {
return reader.peek();
}
@Override
public String getElementText() throws XMLStreamException {
return reader.getElementText();
}
@Override
public XMLEvent nextTag() throws XMLStreamException {
return reader.nextTag();
}
@Override
public Object getProperty(String name) throws IllegalArgumentException {
return reader.getProperty(name);
}
// from Iterator
@Override
public Object next() {
return reader.next();
}
@Override
public void remove() {
reader.remove();
}
@Override
public void close() throws XMLStreamException {
reader.close();
}
/**
* Check if the name of the XML tag which has triggered the passed
* event is to be skipped.
*
* @param event the current event
* @return {@code true} the event should be skipped, otherwise
* {@code false}
*/
private boolean tagToSkip(XMLEvent event) {
switch (event.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
StartElement startTag = (StartElement) event;
return qNames.contains(startTag.getName());
case XMLStreamConstants.END_ELEMENT:
EndElement endTag = (EndElement) event;
return qNames.contains(endTag.getName());
}
return false;
}
}
JAXB类。
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement(name = "XmlParent")
public class FooBar {
private String name;
private String qux;
@XmlElement
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@XmlElement
public String getQux() {
return qux;
}
public void setQux(String qux) {
this.qux = qux;
}
}
显示原则的示例应用程序。
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import sub.optimal.xpath.FooBar;
public class FilteredUnmarshalling {
public static void main(String[] args) throws Exception {
String in = "<XmlParent>\n"
+ " <name>koraytugay</name>\n"
+ " <bar>\n"
+ " <baz>\n"
+ " <qux>00000001</qux>\n"
+ " </baz>\n"
+ " </bar>\n"
+ "</XmlParent>";
byte[] bytes = in.getBytes();
JAXBContext context = JAXBContext.newInstance(FooBar.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
XMLInputFactory factory = XMLInputFactory.newInstance();
String[] tagNamesToFilter = {"bar", "baz"};
Set<QName> tagsToFilter = new HashSet<>();
for (String name : tagNamesToFilter) {
tagsToFilter.add(new QName(name));
}
try (InputStream reader = new ByteArrayInputStream(bytes)) {
XMLEventReader xmlEventReader=factory.createXMLEventReader(reader);
FooBar fooBar = (FooBar)unmarshaller.unmarshal(
new FilteringlXmlEventReader(xmlEventReader,tagsToFilter));
System.out.println("name: " + fooBar.getName());
System.out.println("qux : " + fooBar.getQux());
}
}
}
<强>输出强>
name: koraytugay
qux : 00000001