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

tom*_*eng 4 xml scala

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

val loadnode = scala.xml.XML.loadFile(filename) 
Run Code Online (Sandbox Code Playgroud)

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

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

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

ret*_*nym 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>
Run Code Online (Sandbox Code Playgroud)


huy*_*hjl 5

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

此外,XML 1.1允许您通过使用字符引用在文档中包含控制字符.这涉及控制字符#x1到#x1F,其中大部分都在XML 1.0中被禁止.这意味着您的文档现在可以包含铃声字符,如下所示:?但是,您仍然不能将这些字符直接显示在您的文档中; 这违反了用于XML的mime类型的定义(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
Run Code Online (Sandbox Code Playgroud)

正如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)
Run Code Online (Sandbox Code Playgroud)