我们需要处理一个包含PCDATA元素的XML文件,如下所示:
<corpus id="c01">
<text id="t01>
<sentence id="s01">Mary <instance id="i01">had</instance> a <instance id="i02">lamb</instance>.</sentence>
<sentence id="s02">...</sentence>
...
</text>
...
</corpus>
对于每个&lt;句子&gt;在每个&lt; text&gt;中,我们需要填充包含句子ID和句子所覆盖的全文的数据结构。然后,对于每个&lt; instance&gt;,我们需要填充包含实例ID及其在句子中的开始和结束位置的数据结构。 (我们不关心空白区域是否正常化。)
因此,对于上面的示例,我们基本上需要以下内容:
s.id = "s01"
s.text = "Mary had a lamb."
i1.id = "i01"
i1.start = 6
i1.end = 8
i2.id = "i02"
i2.start = 12
i2.end = 15
有没有办法用dom4j这样做? Element.getText()方法跳过子元素的文本,我没有看到任何方法给出了另一个元素的偏移量。如果dom4j不适合这项任务,那么什么是更好的工具?
答案 0 :(得分:0)
这当然可行,但需要一点工作。您可以创建一个访问者,跟踪它在树中的位置,并在进展时累积文本和实例偏移量。但是,该解决方案也可以直接由SAX处理程序实现,这将快得多。
这应该从一开始就提供:
public class Main extends DefaultHandler {
StringBuilder buf = new StringBuilder();
boolean collecting = false;
int ic = 0;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
if (localName.equals("sentence")) {
System.out.printf("s.id=%s\n", attributes.getValue("id"));
collecting = true;
buf.setLength(0);
ic = 0;
} else if (localName.equals("instance")) {
++ic;
System.out.printf("i%d.id=%s\n", ic, attributes.getValue("id"));
System.out.printf("i%d.start=%s\n", ic, buf.length());
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if (localName.equals("sentence")) {
collecting = false;
System.out.printf("s.text=%s\n", buf.toString());
} else if (localName.equals("instance")) {
System.out.printf("i%d.end=%s\n", ic, buf.length());
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (collecting) {
buf.append(ch, start, length);
}
}
public static void main(String[] args) throws Exception {
SAXParserFactory f = SAXParserFactory.newInstance();
f.setNamespaceAware(true);
f.newSAXParser().parse(Main.class.getResourceAsStream("data.xml"),
new Main());
}
}