Java - 读取XML并保留所有实体

时间:2011-09-12 09:42:10

标签: java xml sax entities stax

我想使用SAX或StAX读取XHTML文件,无论哪种效果最好。 但我不希望实体被解析,替换或类似的东西。 理想情况下,他们应该保持原样。 我不想使用DTD。

这是一个(可执行文件,使用Scala 2.8.x)示例:

import javax.xml.stream._
import javax.xml.stream.events._
import java.io._

println("StAX Test - "+args(0)+"\n")
val factory = XMLInputFactory.newInstance
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false)
factory.setProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES, false)

println("------")
val xer = factory.createXMLEventReader(new FileReader(args(0)))
val entities = new collection.mutable.ArrayBuffer[String]
while (xer.hasNext) {
    val event = xer.nextEvent
    if (event.isCharacters) {
        print(event.asCharacters.getData)
    } else if (event.getEventType == XMLStreamConstants.ENTITY_REFERENCE) {
        entities += event.asInstanceOf[EntityReference].getName
    }
}
println("------")
println("Entities: " + entities.mkString(", "))

给出以下xhtml文件......

<html>
    <head>
        <title>StAX Test</title>
    </head>
    <body>
        <h1>Hallo StAX</h1>
        <p id="html">
            &lt;div class=&quot;header&quot;&gt;
        </p>
        <p id="stuff">
            &Uuml;berdies sollte das hier auch als Copyright sichtbar sein: &#169;
        </p>
        Das war's!
    </body>
</html>

...正在运行scala stax-test.scala stax-test.xhtml会导致:

StAX Test - stax-test.xhtml

------


    StAX Test


    Hallo StAX

      <div class="header">


      berdies sollte das hier auch als Copyright sichtbar sein: ?

    Das war's!

------
Entities: Uuml

所以所有实体都或多或少都成功了。 我想要的和我想要的是这个,但是:

StAX Test - stax-test.xhtml

------


    StAX Test


    Hallo StAX

      &lt;div class=&quot;header&quot;&gt;


      &Uuml;berdies sollte das hier auch als Copyright sichtbar sein: &#169;

    Das war's!

------
Entities: // well, or no entities above and instead:
// Entities: lt, quot, quot, gt, Uuml, #169

这甚至可能吗? 我想解析XHTML,做一些修改,然后再将它输出为XHTML。所以我真的希望实体留在结果中。

另外,我不明白为什么Uuml被报告为EntityReference事件,而其余事件则没有。

3 个答案:

答案 0 :(得分:2)

一些术语:&#x169;是数字字符引用(不是实体),&#auml;是实体引用(不是实体)。

我认为任何XML解析器都不会报告应用程序的数字字符引用 - 它们将始终被扩展。实际上,你的应用程序不应该关心这个,而是关心属性之间有多少空格。

对于实体引用,SAX等低级解析接口将报告实体引用的存在 - 无论如何,它会在元素内容中报告它们,但不会在属性内容中报告。有些特殊事件只通知LexicalHandler而不是ContentHandler。

答案 1 :(得分:1)

“为什么Uuml被报告为EntityReference事件而其余部分未被报告”的答案是其余部分由XML规范定义,而&Uuml;特定于HTML 4.0

由于您的目标是编写修改后的XHTML,因此可能通过将“encoding”设置为“US-ASCII”和/或“方法”来强制序列化程序发出数字实体引用“to”html“。 XSLT spec(它是Java XML序列化程序的基础)表示当方法为html时,序列化程序“可以使用字符实体引用输出字符”。如果不支持命名实体,则将编码设置为ASCII可能会强制它使用数字实体。

答案 2 :(得分:-2)

在Java中我会使用正则表达式。

public static void main(String... args) throws IOException {
  BufferedReader buf = new BufferedReader(new FileReader(args[0]));
  Pattern entity = Pattern.compile("&([^;]+);");
  Set<String> entities = new LinkedHashSet<String>();
  for (String line; (line = buf.readLine()) != null; ) {
    Matcher m = entity.matcher(line);
    while (m.find())
      entities.add(m.group(1));
  }
  buf.close();
  System.out.println("Entities: " + entities);
}

打印

Entities: [lt, quot, gt, Uuml, #169]