我可以使用Scala的内置xml处理程序忽略无效的XML字符吗?

时间:2010-03-10 01:34:49

标签: xml scala

我有一个xml文件(来自联邦政府的data.gov),我正在尝试用scala的xml处理程序阅读。

val loadnode = scala.xml.XML.loadFile(filename) 

显然,xml字符无效。是否可以选择忽略无效字符?或者是我唯一可以先清理它的选择?

org.xml.sax.SAXParseException: An invalid XML character (Unicode: 0x12) was found in the element content of the document.

Ruby的nokogiri能够用无效字符解析它。

3 个答案:

答案 0 :(得分:10)

要扩展@ huynhjl的答案:如果您有多字节字符,InputStream过滤器是危险的,例如UTF-8编码文本。相反,使用面向字符的过滤器:FilterReader。或者,如果文件足够小,请加载到String并替换那里的字符。

scala> val origXml = "<?xml version='1.1'?><root>\u0012</root>"                                          
origXml: java.lang.String = <?xml version='1.1'?><root></root>

scala> val cleanXml = xml flatMap { 
   case x if Character.isISOControl(x) => "&#x" + Integer.toHexString(x) + ";"
   case x => Seq(x) 
}
cleanXml: String = <?xml version='1.1'?><root>&#x12;</root>

scala> scala.xml.XML.loadString(cleanXml) 
res14: scala.xml.Elem = <root></root>

答案 1 :(得分:5)

我想知道即使在XML 1.1中0x12是否有效。有关1.0与1.1的差异,请参阅此summary。特别是:

  

此外,XML 1.1允许您   你的控制角色   文件通过使用字符   引用。这涉及控制   字符#x1到#x1F,大部分   在XML 1.0中禁止使用。这个   表示您的文档现在可以   包括钟形字符,如下所示:   ?。但是,你仍然不能拥有   这些字符直接出现在   你的文件;这违反了   用于的mime类型的定义   XML(text / xml)。

Xerces可以解析XML 1.1,但似乎期望实体&#18;而不是真正的0x12字符:

val s = "<?xml version='1.1'?><root>\u0012</root>"
// causes An invalid XML character (Unicode: 0x12)
//XML.loadXML(xml.Source.fromString(s), XML.parser)

val u = "<?xml version='1.1'?><root>&#18;</root>"
val v = XML.loadXML(xml.Source.fromString(u), XML.parser)
println(v) // works

根据lavinio的建议,您可以过滤掉无效字符。这在Scala中不需要太多行:

val in = new InputStream {
  val in0 = new FileInputStream("invalid.xml")
  override def read():Int = in0.read match { case 0x12=> read() case x=> x}
}
val x = XML.load(in)

答案 2 :(得分:3)

0x12仅在XML 1.1中有效。如果您的XML文件说明了该版本,那么您可以在SAX解析器中启用1.1处理支持。

否则,底层解析器可能是Xerces,作为一个符合要求的XML解析器,它正在抱怨。

如果你必须处理这些流,我会在输入文件周围写一个包装器InputStream或Reader,过滤掉带有无效Unicode值的字符,然后传递其余部分。