[英]Parsing an XML in Java using STax
This, even to me, seems like a silly question but then is one of those to which i cant find an answer. 甚至对我来说,这似乎是一个愚蠢的问题,但这是我找不到答案的问题之一。
Im trying to parse an XML using STax in Java and the XMl im trying to parse looks like this -- 我试图使用Java中的STax解析XML,而XMl我试图解析的样子是这样的-
<?xml version="1.0" encoding="UTF-8"?>
<Macros>
<MacroDefinition>
<MacroName>
<string>Macro1</string>
</MacroName>
</MacroDefinition>
</Macros>
Now i have a Macro class as follows -- 现在我有一个宏类如下-
public class Macro {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
I also have a parser class from where i try to convert the XML into an object of the 'Macro' class. 我也有一个解析器类,从那里我试图将XML转换为'Macro'类的对象。 The parser class snippet is as follows --
解析器类代码段如下-
public class StaxParser {
static final String MACRODEFINITION = "MacroDefinition";
static final String MACRONAME = "MacroName";
static final String STRING = "string";
@SuppressWarnings({ "unchecked", "null" })
public List<Item> readMacro(String configFile) {
List<Macro> macroList = new ArrayList<Macro>();
try {
// First create a new XMLInputFactory
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
// Setup a new eventReader
InputStream in = new FileInputStream(configFile);
XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
// Read the XML document
Macro macro = null;
while (eventReader.hasNext()) {
XMLEvent event = eventReader.nextEvent();
if (event.isStartElement()) {
StartElement startElement = event.asStartElement();
if (startElement.getName().getLocalPart() == (MACRODEFINITION)) {
macro = new Macro();
}
if (event.isStartElement()) {
if (event.asStartElement().getName().getLocalPart()
.equals(MACRONAME)) {
Iterator<Attribute> attributes = event
.asStartElement().getAttributes();
while (attributes.hasNext()) {
Attribute attribute = attributes.next();
if (attribute.getName().toString()
.equals(STRING)) {
macro.setMacroName(event.asCharacters()
.getData());
}
}
event = eventReader.nextEvent();
continue;
}
}
}
// If we reach the end of an item element we add it to the list
if (event.isEndElement()) {
EndElement endElement = event.asEndElement();
if (endElement.getName().getLocalPart() == (MACRODEFINITION)) {
macroList.add(macro);
}
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (XMLStreamException e) {
e.printStackTrace();
}
return macroList;
}
}
The problem im facing is that the parser is not able to read the child nodes of 'MacroName'. 面临的问题是解析器无法读取“ MacroName”的子节点。 Im thinking
getAttributes
is what is causing it not to work but have no clue of what method i should be calling to get the child nodes of any particular node. 我以为
getAttributes
是导致它无法工作的原因,但是不知道我应该调用哪种方法来获取任何特定节点的子节点。
Any help with this would be greatly appreciated. 任何帮助,将不胜感激。
Thanks 谢谢
p1nG p1nG
Sorry to say that, but your code has many issues and doesn't even compile. 不好意思地说,但是您的代码有很多问题,甚至没有编译。
First of all, the return type should be List<Macro>
, since the Macro
class doesn't inherit from, nor implement, the Item
. 首先,返回类型应为
List<Macro>
,因为Macro
类既不继承也不实现Item
。
Second, you should ensure a safe nesting, to follow the schema of your XML, not arbitrarily test for event name equality and create Macro
objects here and there along the way. 其次,您应该确保安全嵌套,以遵循XML的架构,而不是随意测试事件名称的相等性,并一路在各处创建
Macro
对象。 If you plan to retreive also other data besides the macro name, you can't get away with just checking for the STRING
event occurence. 如果您还打算检索除宏名称之外的其他数据,那么仅检查
STRING
事件是否发生就无法摆脱。
Third, it's useless to nest the same checks, eg event.isStartElement()
. 第三,嵌套相同的检查是没有用的,例如
event.isStartElement()
。
Fourth, you should provide a Source
or a Reader
or a Stream
to a class such as the StaxParser, not directly a filename, but I didn't include this change to avoid breaking your API. 第四,您应该为诸如StaxParser之类的类提供
Source
或Reader
或Stream
,而不是直接提供文件名,但为了避免破坏您的API,我没有提供此更改。
class StaxParser {
static final String MACRODEFINITION = "MacroDefinition";
static final String MACRONAME = "MacroName";
static final String STRING = "string";
@SuppressWarnings({ "unchecked", "null" })
public List<Macro> readMacro(final String configFile) {
final List<Macro> macroList = new ArrayList<Macro>();
try {
// First create a new XMLInputFactory
final XMLInputFactory inputFactory = XMLInputFactory.newInstance();
// Setup a new eventReader
final InputStream in = new FileInputStream(configFile);
final XMLEventReader eventReader = inputFactory.createXMLEventReader(in);
// Read the XML document
final Template template = getTemplate(eventReader);
macroList.addAll(template.process(null, getMacrosProcessor(template)));
} catch (final FileNotFoundException e) {
e.printStackTrace();
} catch (final XMLStreamException e) {
e.printStackTrace();
}
return macroList;
}
interface Template {
<T> T process(String parent, EventProcessor<T> ep) throws XMLStreamException;
}
static Template getTemplate(final XMLEventReader eventReader) {
return new Template() {
@Override
public <T> T process(final String parent, final EventProcessor<T> ep) throws XMLStreamException {
T t = null;
boolean process = true;
while (process && eventReader.hasNext()) {
final XMLEvent event = eventReader.nextEvent();
if (ep.acceptsEvent(event)) {
t = ep.processEvent(event);
}
if (event.isEndElement()) {
if (null != parent && parent.equals(event.asEndElement().getName().getLocalPart())) {
process = false;
}
}
}
return t;
}
};
}
interface EventProcessor<T> {
boolean acceptsEvent(XMLEvent event);
T processEvent(XMLEvent event) throws XMLStreamException;
}
static EventProcessor<List<Macro>> getMacrosProcessor(final Template template) {
final List<Macro> macroList = new ArrayList<Macro>();
return new EventProcessor<List<Macro>>() {
@Override
public boolean acceptsEvent(final XMLEvent event) {
return event.isStartElement()
&& MACRODEFINITION.equals(event.asStartElement().getName().getLocalPart());
}
@Override
public List<Macro> processEvent(final XMLEvent event) throws XMLStreamException {
macroList.add(template.process(MACRODEFINITION, getMacroDefinitionProcessor(template)));
return macroList;
}
};
}
static EventProcessor<Macro> getMacroDefinitionProcessor(final Template template) {
return new EventProcessor<Macro>() {
@Override
public boolean acceptsEvent(final XMLEvent event) {
return event.isStartElement() && MACRONAME.equals(event.asStartElement().getName().getLocalPart());
}
@Override
public Macro processEvent(final XMLEvent event) throws XMLStreamException {
final Macro macro = new Macro();
macro.setName(template.process(MACRONAME, getMacroNameProcessor(template)));
return macro;
}
};
}
static EventProcessor<String> getMacroNameProcessor(final Template template) {
return new EventProcessor<String>() {
@Override
public boolean acceptsEvent(final XMLEvent event) {
return event.isStartElement() && STRING.equals(event.asStartElement().getName().getLocalPart());
}
@Override
public String processEvent(final XMLEvent event) throws XMLStreamException {
return template.process(STRING, getStringProcessor());
}
};
}
static EventProcessor<String> getStringProcessor() {
return new EventProcessor<String>() {
@Override
public boolean acceptsEvent(final XMLEvent event) {
return event.isCharacters();
}
@Override
public String processEvent(final XMLEvent event) throws XMLStreamException {
return event.asCharacters().getData();
}
};
}
}
First notice that Macro1 is not XML attribute, so event attributes will be empty. 首先请注意Macro1不是XML属性,因此事件属性将为空。 Code after changes ( I have only shown lines of code that may be of interest ):
更改后的代码( 我只显示了可能感兴趣的代码行 ):
if (event.isStartElement()
&& event.asStartElement().getName().getLocalPart().equals(STRING)) {
if (macro == null) {
macro = new Macro();
}
macro.setName(eventReader.getElementText());
}
A few tips: never ever compare strings using == use equals method. 一些提示:永远不要使用==使用equals方法比较字符串。 If you need full working example I could post my solution, but it is bit more complicated.
如果您需要完整的工作示例,我可以发布我的解决方案,但这要复杂一些。
You have to change macro.setMacroName(event.asCharacters().getData()); 您必须更改macro.setMacroName(event.asCharacters()。getData());
to macro.setMacroName(attribute.getvalue().toString()); 到macro.setMacroName(attribute.getvalue()。toString());
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.