如何使用 stax/stax2 获取 XML 元素路径?
How to get XML element path using stax/stax2?
我想在使用 java StAX2 解析器解析 XML 时获取元素路径。
如何获取当前元素路径信息?
<root>
<a><b>x</b></a>
</root>
在此示例中,路径为 /root/a/b
。
保留堆栈。在 START_ELEMENT 上推送元素名称并在 END_ELEMENT 上弹出它。
这是一个简短的例子。除了打印正在处理的元素的路径外,它什么都不做。
public static void main(String[] args) throws IOException, XMLStreamException {
try (FileInputStream in = new FileInputStream("test.xml")) {
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLStreamReader reader = factory.createXMLStreamReader(in);
LinkedList<String> path = new LinkedList<>();
int next;
while ((next = reader.next()) != XMLStreamConstants.END_DOCUMENT) {
switch (next) {
case XMLStreamConstants.START_ELEMENT:
// push the name of the current element onto the stack
path.addLast(reader.getLocalName());
// print the path with '/' delimiters
System.out.println("Reading /" + String.join("/", path));
break;
case XMLStreamConstants.END_ELEMENT:
// pop the name of the element being closed
path.removeLast();
break;
}
}
}
}
"The chronicler's duty"
方法一:专用栈,@teppic建议
try (InputStream in = new ByteArrayInputStream(xml.getBytes())) {
final XMLInputFactory2 factory = (XMLInputFactory2) XMLInputFactory.newInstance();
final XMLStreamReader2 reader = (XMLStreamReader2) factory.createXMLStreamReader(in);
Stack<String> pathStack = new Stack<>();
while (reader.hasNext()) {
reader.next();
if (reader.isStartElement()) {
pathStack.push(reader.getLocalName());
processPath('/' + String.join("/", pathStack));
} else if (reader.isEndElement()) {
pathStack.pop();
}
}
}
方法二(丑):黑客攻击Woodstox'sInputElementStack
实施适配器以访问 InputElementStack
、其受保护的 mCurrElement
并与父级交互(这会减慢算法速度)。
package com.ctc.wstx.sr;
import java.util.LinkedList;
public class StackUglyAdapter {
public static String PATH_SEPARATOR = "/";
private InputElementStack stack;
public StackUglyAdapter(InputElementStack stack) {
this.stack = stack;
}
public String getCurrElementLocalName() {
return this.stack.mCurrElement.mLocalName;
}
public String getCurrElementPath() {
LinkedList<String> list = new LinkedList<String>();
Element el = this.stack.mCurrElement;
while (el != null) {
list.addFirst(el.mLocalName);
el = el.mParent;
}
return PATH_SEPARATOR+String.join(PATH_SEPARATOR,list);
}
}
使用示例:
try (final InputStream in = new ByteArrayInputStream(xml.getBytes())) {
final XMLInputFactory2 factory =
(XMLInputFactory2) XMLInputFactory.newInstance();
final XMLStreamReader2 reader =
(XMLStreamReader2) factory.createXMLStreamReader(in);
final StackUglyAdapter stackAdapter =
new StackUglyAdapter(((StreamReaderImpl) reader).getInputElementStack());
while (reader.hasNext()) {
reader.next();
if (reader.isStartElement()) {
processPath(stackAdapter.getCurrElementPath());
}
}
}
带有专用堆栈的方法 1 更好,因为 API 独立于实现并且与 方法 2[=35 一样快=].
我想在使用 java StAX2 解析器解析 XML 时获取元素路径。 如何获取当前元素路径信息?
<root>
<a><b>x</b></a>
</root>
在此示例中,路径为 /root/a/b
。
保留堆栈。在 START_ELEMENT 上推送元素名称并在 END_ELEMENT 上弹出它。
这是一个简短的例子。除了打印正在处理的元素的路径外,它什么都不做。
public static void main(String[] args) throws IOException, XMLStreamException {
try (FileInputStream in = new FileInputStream("test.xml")) {
XMLInputFactory factory = XMLInputFactory.newFactory();
XMLStreamReader reader = factory.createXMLStreamReader(in);
LinkedList<String> path = new LinkedList<>();
int next;
while ((next = reader.next()) != XMLStreamConstants.END_DOCUMENT) {
switch (next) {
case XMLStreamConstants.START_ELEMENT:
// push the name of the current element onto the stack
path.addLast(reader.getLocalName());
// print the path with '/' delimiters
System.out.println("Reading /" + String.join("/", path));
break;
case XMLStreamConstants.END_ELEMENT:
// pop the name of the element being closed
path.removeLast();
break;
}
}
}
}
"The chronicler's duty"
方法一:专用栈,@teppic建议
try (InputStream in = new ByteArrayInputStream(xml.getBytes())) {
final XMLInputFactory2 factory = (XMLInputFactory2) XMLInputFactory.newInstance();
final XMLStreamReader2 reader = (XMLStreamReader2) factory.createXMLStreamReader(in);
Stack<String> pathStack = new Stack<>();
while (reader.hasNext()) {
reader.next();
if (reader.isStartElement()) {
pathStack.push(reader.getLocalName());
processPath('/' + String.join("/", pathStack));
} else if (reader.isEndElement()) {
pathStack.pop();
}
}
}
方法二(丑):黑客攻击Woodstox'sInputElementStack
实施适配器以访问
InputElementStack
、其受保护的mCurrElement
并与父级交互(这会减慢算法速度)。package com.ctc.wstx.sr; import java.util.LinkedList; public class StackUglyAdapter { public static String PATH_SEPARATOR = "/"; private InputElementStack stack; public StackUglyAdapter(InputElementStack stack) { this.stack = stack; } public String getCurrElementLocalName() { return this.stack.mCurrElement.mLocalName; } public String getCurrElementPath() { LinkedList<String> list = new LinkedList<String>(); Element el = this.stack.mCurrElement; while (el != null) { list.addFirst(el.mLocalName); el = el.mParent; } return PATH_SEPARATOR+String.join(PATH_SEPARATOR,list); } }
使用示例:
try (final InputStream in = new ByteArrayInputStream(xml.getBytes())) { final XMLInputFactory2 factory = (XMLInputFactory2) XMLInputFactory.newInstance(); final XMLStreamReader2 reader = (XMLStreamReader2) factory.createXMLStreamReader(in); final StackUglyAdapter stackAdapter = new StackUglyAdapter(((StreamReaderImpl) reader).getInputElementStack()); while (reader.hasNext()) { reader.next(); if (reader.isStartElement()) { processPath(stackAdapter.getCurrElementPath()); } } }
带有专用堆栈的方法 1 更好,因为 API 独立于实现并且与 方法 2[=35 一样快=].