Scala 2.13+ 已移除 scala.xml,其模式匹配因运行时类型擦除、无命名空间支持、属性缺失返回空Text、不校验结构等缺陷而脆弱;推荐改用 jsoup 等健壮库。
Scala 原生 XML 支持(scala.xml)已自 Scala 2.13 起被移除,不再推荐用于新项目;如果你正在维护旧代码或必须使用它,模式匹配确实是其最典型的解析方式——但要注意它不是“安全”或“健壮”的 XML 解析方案。
sc
ala.xml 的模式匹配容易出错它依赖字符串级的 XML 字面量结构与运行时类型擦除,不校验命名空间、不处理 CDATA、不支持流式解析,且对空元素/属性缺失/类型转换极其脆弱。
NodeSeq 匹配可能意外捕获注释或文本节点elem \@ "id" 在属性不存在时返回空 Text,而非 None
case 模式假设有如下 XML:
val xml =Scala in Depth Joshua Suereth
你可以这样匹配:
xml match {
case {titleElem @ {_*} }{authorElem @ {_*}} =>
val idStr = id.toString
val title = (titleElem \ "_text").text.toString.trim
val author = (authorElem \ "_text").text.toString.trim
(idStr, title, author)
case _ => throw new IllegalArgumentException("Unexpected XML structure")
}
{id} 提取属性值,但 id 是 NodeSeq,需调用 .toString
{_*} 表示“任意子节点”,不能直接当字符串用,得再用 \ "_text" 或 text
\ 是 XPath 风格查找,但只支持极简语法(如 \ "title"),不支持谓词或轴scala-xml + scala-parser-combinators?别有人试图补救,比如用 XML.loadString 加 scala-parser-combinators 写更严格的解析器——这反而叠加了两套不一致的抽象,问题更多。
SAXParseException,但模式匹配无法覆盖该异常路径Option-friendly 属性提取(比如 elem.attribute("id").map(_.text) 才算合理)scala.xml 对 xmlns 几乎无感知)生产环境请直接切换到成熟库:
javax.xml.parsers.DocumentBuilder(JDK 自带)+ scala.xml.XML 仅作字符串转义辅助scalaxb(XSD 绑定)、spray-json 风格的 xml-util(如 com.lihaoyi:upickle 不支持 XML,但 net.ruippeixotog:scala-scraper 可用于 HTML/XML 混合场景)org.jsoup:jsoup(即使不是 HTML,它对 malformed XML 容错更强,且 API 返回 Option)例如用 jsoup 提取:
import org.jsoup.Jsoup
val doc = Jsoup.parse(xml.toString, "", org.jsoup.parser.Parser.xmlParser())
val id = doc.select("book").attr("id") // 返回 String,默认空串
val title = doc.select("title").text() // 安全,无子节点则返回空串
真正麻烦的从来不是“怎么写模式匹配”,而是 XML 结构稍有变动(比如加个 或属性变成 data-id),旧匹配逻辑就静默失效——而这种错误不会在编译期暴露。