2011-10-25 39 views
0

覆蓋文本,我們需要處理包含PCDATA元素,如下面的XML文件:元偏移和dom4j的

<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> 

對於每個<文本>的各<句子>,我們需要填充的數據結構包含句子ID和句子所涵蓋的全文。然後,對於每個<實例>,我們需要填充包含實例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

這當然是可行的,但需要一點工作。您可以創建一個Visitor來跟蹤它在樹中的位置,並在文本和實例偏移隨着進展而累積。但是,該解決方案可以直接由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()); 
} 
}