即使对我来说,这似乎是一个愚蠢的问题,但那是我无法找到答案的那一个。
我试图使用Java中的STax解析XML,而我试图解析的XMl看起来像这样 -
<?xml version="1.0" encoding="UTF-8"?>
<Macros>
<MacroDefinition>
<MacroName>
<string>Macro1</string>
</MacroName>
</MacroDefinition>
</Macros>
现在我有一个Macro类,如下所示 -
public class Macro {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我还有一个解析器类,我尝试将XML转换为'Macro'类的对象。解析器类片段如下 -
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;
}
}
我面临的问题是解析器无法读取'MacroName'的子节点。我想getAttributes
是什么导致它无法工作,但不知道我应该调用什么方法来获取任何特定节点的子节点。
任何有关这方面的帮助将不胜感激
由于
p1nG
答案 0 :(得分:3)
很抱歉这么说,但是你的代码有很多问题,甚至没有编译。
首先,返回类型应为List<Macro>
,因为Macro
类不会继承,也不会实现Item
。
其次,您应确保安全嵌套,遵循XML的架构,而不是随意测试事件名称相等性,并在此过程中随时创建Macro
个对象。如果您打算同时检索除宏名称之外的其他数据,那么只需检查STRING
事件是否发生就无法实现。
第三,嵌套相同的支票是没用的,例如event.isStartElement()
。
第四,您应该向一个类(例如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();
}
};
}
}
答案 1 :(得分:2)
首先注意Macro1不是XML属性,因此事件属性将为空。更改后的代码(我只显示了可能感兴趣的代码行):
if (event.isStartElement()
&& event.asStartElement().getName().getLocalPart().equals(STRING)) {
if (macro == null) {
macro = new Macro();
}
macro.setName(eventReader.getElementText());
}
一些提示:永远不要使用== use equals方法比较字符串。如果你需要完整的工作示例,我可以发布我的解决方案,但它有点复杂。
答案 2 :(得分:0)
你必须改变 macro.setMacroName(event.asCharacters()的getData());
要 macro.setMacroName(attribute.getvalue()的toString());