java - 在Java中按行号和行位置检索XML节点
问题描述
我们正在接收根据规范有效的 XML 文件。有一个外部方检查原始 XML 文件并根据 XML 文件的内容生成警告。如果有警告,这将产生两个文件:
- 原始 XML 文件。
- 包含与 XML 文件相关的警告/错误的文件。
问题在于,对于每个警告,它们都会通过行号和行位置来引用原始文件中的警告。
<PositionInBericht>
<LineNumber>78</LineNumber>
<LinePosition>10</LinePosition>
</PositionInBericht>
不幸的是,我们无法改变它,因为它在规范中写到它应该表现得像这样。我在互联网上搜索示例,但没有太多可以找到我想要的东西。
我找到的资源是:
我应该如何使用行号和列号在 JAVA 中获取 XML 中的元素 如何使用行号和列号在 JAVA 中获取 XML 中的元素
Java / Groovy:按行号查找 XML 节点 Java / Groovy:按行号查找 XML 节点
这些帖子中提供的解决方案不是最理想的或不存在的。我想知道人们是否曾经这样做过并想出了一个好的解决方案。
编辑:
为了帮助人们,我找到了解决方案。它基本上做了以下事情:指定行号,它会打印出起始元素的信息。
public class ParsingByLineNumberApplication {
/**
* URL's gebruikt ter inspiratie voor dit project.
*
* How should I use line number and column number to get element in XML in JAVA
* https://stackoverflow.com/questions/41225724/how-should-i-use-line-number-and-column-number-to-get-element-in-xml-in-java
*
* Java / Groovy : Find XML node by Line number
* https://stackoverflow.com/questions/47701357/java-groovy-find-xml-node-by-line-number
*
* Parsing XML documents partially with StAX
* https://www.ibm.com/developerworks/library/x-tipstx2/index.html
*
* @param args
* @throws FileNotFoundException
* @throws XMLStreamException
* @throws URISyntaxException
*/
public static void main(String[] args) throws FileNotFoundException, XMLStreamException, URISyntaxException {
printElementsAtLineNumber(53);
}
private static void printElementsAtLineNumber(int lineNumber) throws URISyntaxException, FileNotFoundException, XMLStreamException {
URL resource = ParsingByLineNumberApplication.class.getClassLoader().getResource("test_file.XML");
FileReader reader = new FileReader(new File(resource.toURI()));
XMLInputFactory factory = XMLInputFactory.newInstance();
XMLStreamReader xmlr = factory.createXMLStreamReader(reader);
// Create a filtered stream reader
XMLStreamReader xmlfr = factory.createFilteredReader(xmlr, filter);
// Main event loop
while (xmlfr.hasNext()) {
// Process single event
if (xmlfr.getEventType() == XMLStreamConstants.START_ELEMENT) {
if (lineNumber == xmlfr.getLocation().getLineNumber()) {
System.out.println("Character offset: " + xmlfr.getLocation().getCharacterOffset());
System.out.println("Column number: " + xmlfr.getLocation().getColumnNumber());
System.out.println("Element name: " + xmlfr.getName().getLocalPart());
System.out.println("Line number: " + xmlr.getLocation().getLineNumber());
System.out.println("Element text: " + xmlr.getElementText());
}
}
// Move to next event
xmlfr.next();
}
}
private static QName[] exclude = new QName[]{
new QName("invoice"), new QName("item")};
private static StreamFilter filter = new StreamFilter() {
// Element level
int depth = -1;
// Last matching path segment
int match = -1;
// Filter result
boolean process = true;
// Character position in document
int currentPos = -1;
public boolean accept(XMLStreamReader reader) {
// Get character position
Location loc = reader.getLocation();
int pos = loc.getCharacterOffset();
// Inhibit double execution
if (pos != currentPos) {
currentPos = pos;
switch (reader.getEventType()) {
case XMLStreamConstants.START_ELEMENT:
// Increment element depth
if (++depth < exclude.length && match == depth - 1) {
// Compare path segment with current element
if (reader.getName().equals(exclude[depth]))
// Equal - set segment pointer
match = depth;
}
// Process all elements not in path
process = match < exclude.length - 1;
break;
// End of XML element
case XMLStreamConstants.END_ELEMENT:
// Process all elements not in path
process = match < exclude.length - 1;
// Decrement element depth
if (--depth < match)
// Update segment pointer
match = depth;
break;
}
}
return process;
}
};
}
解决方案
SAX 解析器显示行号信息;DOM 解析器(以及更高级别的工具,如 JAXB)通常不会。我不知道一旦你找到了这些信息你想对它做什么,但是编写你的应用程序来使用 SAX 听起来像是一项艰巨的工作。
如果您使用 Saxon,那么您可以选择在构建的树中保留行号和列号(Saxon 从 SAX 解析器获取信息并将其保留在树中)。例如,您可以DocumentBuilder.setLineNumbering()
在 s9api 接口中使用此请求。如果您使用 XSLT、XPath 或 XQuery,那么您可以使用扩展函数saxon:line-number()
或saxon:column-number()
(需要 Saxon-PE 或 -EE)来获取信息。您还可以从导航树的 Java 应用程序获取信息。
请注意,为元素返回的行号和列号是在 SAX 规范中定义的:具体来说,“>”在开始标记末尾的位置。这可能不完全反映数据文件中给出的行和列。
推荐阅读
- javascript - Javascript, CSS, HTML - 点击屏幕使下拉菜单消失
- postgresql - 如何将我的独立(本地)postgres 数据库同步到云(AWS RDS)?
- javascript - 反应:当值为“未定义”时,内联如果不解析为假
- sql - 通过排除计数和分组?
- python - 跟踪最佳索引,同时每次迭代将矩阵减少 1x1
- sql - 在 Select 语句中,根据日期间隔添加记录
- python-3.x - 你能从另一个线程杀死一个 Tk 应用程序吗?如果没有,是否可以轻松地向主线程发送布尔消息?
- elasticsearch - 为什么我的 ES 协调节点安装目录的根目录中有一个巨大的“数据”文件?
- sql - 列不允许空值。插入失败:SQL R 服务
- http - 阻止/拒绝所有未按位置映射的请求