Как я могу извлечь все PCDATA (текст) из XML-файла на Java?

#java #xml #xml-parsing

#java #xml #синтаксический анализ xml

Вопрос:

У меня есть куча XML-файлов вместе с DTD, каждый из которых имеет <TEXT> раздел. DTD для TEXT элемента выглядит следующим образом:

<!ELEMENT TEXT - - (AGENCY* | ACTION* | SUMMARY* | DATE* | FOOTNAME* | FURTHER* | SIGNER* | SIGNJOB* | FRFILING* | BILLING* | FOOTNOTE* | FOOTCITE* | TABLE* | ADDRESS* | IMPORT* | #PCDATA) >

Вот как будет выглядеть пример XML-файла:

 <ROOT>
  ...
  <TEXT>
  Some text that I want to extract
  <SUMMARY> Some more text </SUMMARY>
  <AGENCY> 
     An agency
     <SIGNER> Bob Smith </SIGNER>
  </AGENCY>
  </TEXT>
  ...
</ROOT>
  

В конце я хочу извлечь

Некоторый текст, который я хочу извлечь, еще немного текста, предоставленного агентством Bob Smith

Однако каждый <TEXT> блок, очевидно, не одинаков с точки зрения элементов / порядка или того, как далеко вы продвинулись. Есть ли способ в Java с использованием DOM, которым я могу это сделать? Я бы предпочел использовать DOM вместо SAX, но если использовать SAX намного проще, то пусть будет так.

Заранее спасибо

Ответ №1:

Таблица стилей XSLT будет работать:

ОБНОВЛЕНИЕ # 2: Я сомневаюсь, что это сработает для вас, поскольку вы фактически используете SGML, а не XML. Проблема заключается в том, что объявление элемента, которое вы имеете в своем вопросе, имеет минимизацию тегов, которая не разрешена в XML.

ОБНОВЛЕНИЕ: Изменен ввод XML и XSLT, чтобы отображать только текст в <TEXT> структуре.

ВВОД XML

 <ROOT>
  <IGNORE>ignore this data</IGNORE>
  <TEXT>
    Some text that I want to extract
    <SUMMARY> Some more text </SUMMARY>
    <AGENCY> 
      An agency
      <SIGNER> Bob Smith </SIGNER>
    </AGENCY>
  </TEXT>
  <IGNORE>ignore this data</IGNORE>
</ROOT>
  

XSLT

 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="text"/>

  <xsl:template match="/">
    <xsl:value-of select="normalize-space(/ROOT/TEXT)"/>
  </xsl:template>

</xsl:stylesheet>
  

ВЫВОД

Некоторый текст, который я хочу извлечь, еще немного текста, предоставленного агентством Bob Smith

Примечание: Этот XSLT работает, только если TEXT является дочерним элементом ROOT. Если ТЕКСТ может быть вложен более глубоко, вы можете изменить «выбрать» на select="normalize-space(//TEXT)" .

Комментарии:

1. Вы правы, это SGML, но до сих пор он был совместим с XML

Ответ №2:

Я не большой поклонник SAX, но для этого, я думаю, это будет хорошо работать.

Просто определите обработчик sax, но используйте только characters метод. Затем просто добавьте полученные символы в StringBuilder и все готово.

 public class textExtractor extends DefaultHandler {

  private StringBuilder sb = new StringBuilder();

  public void characters(char[] ch, int start, int length){
    for (int i=0; i<length; i  ){
      sb.append(ch[i]);
    }
  }

  public String getText(){
    return sb.toString();
  }

}
  

Комментарии:

1. Я думаю, что я воспользуюсь этим подходом. должен ли обработчик sax быть его собственным классом? или я могу просто расширить родительский класс моего основного метода?

2. Вы можете расширить родительский класс, но я бы не рассматривал это как новый подход. Если вы не хотите создавать для этого определенный класс, вы можете использовать анонимный класс.