在Scala中查找名称中带有通配符的XML节点

时间:2018-04-18 18:52:37

标签: xml scala xpath

我有以下XML:

<data>
    <a>...</a>
    <b1>...</b1>
    <c>...</c>
    <b2>...</b2>
    <d>...</d>
    <b3>...</b2>
</data>

在Scala中,如何从data节点(即Elem对象)中提取以字符串“b”开头的节点?在这种情况下,所需的值是三个节点的序列:

[<b1>...</b1>, <b2>...</b2>, <b3>...</b3]

我试过这个,但它没有编译:

val orderNodes: NodeSeq = /data/*[starts-with(name(), "b")]

2 个答案:

答案 0 :(得分:1)

小文档最简单的解决方案是使用您需要的谓词过滤节点序列:

val data = <data>
  <a>...</a>
  <b1>...</b1>
  <c>...</c>
  <b2>...</b2>
  <d>...</d>
  <b3>...</b3>
</data>

scala> (data \ "_").filter(_.label.startsWith("b"))
res1: scala.xml.NodeSeq = NodeSeq(<b1>...</b1>, <b2>...</b2>, <b3>...</b3>)

elem \ label语法返回一系列节点,其名称完全等于labelelem \ "_"是该语法的特例,它返回所有子元素。然后,您可以使用与任何普通Scala集合一样的节点序列。

答案 1 :(得分:0)

您可以使用scala.xml.XML.EventReader,它按标记读取XML文件标记。

有3个案例是starTag,text和endTag,你可以从XML文件中提取你想要的数据。

e.g。 //scala.io.Source

val source = new Source(“path to XML file”)
val eventReader=new EventReader(source)
parse(xml)
def parse ={
var isStartTag= false
var isEndTag = false
var list = mutable.List()
loop(currentNode) // tail recursive function
If(xml.hasNext){
xml.next match{

case startEvent(_,label,_,_) => //your logic
loop(currentNode)

case Text(text)=> // your logic 
loop(currentNode )

case EndEvent => // your logic
loop(currentNode.tail)

case _ => loop(currentNode.tail)}}
loop(Nil)}

这样的东西可能会有一些合成错误。但想法是阅读您感兴趣的标签并进行处理。

它还可以帮助您实现真正的猪油文件,因为您只会将感兴趣的标签加载到内存中。

如果您有Elem对象,那么您可以这样做。 从Elem对象获取nodeSeq,并执行此操作。

node \\“your parent tag”\\“your child tag”

在您孩子和父母标签的位置,您可以提供正则表达式。

与节点\\“abc *”\\“b *”

类似

如果您确定孩子在场,您可以使用。

node \\“您的父标记”\“您的子标记”