我正在拉解析一个xml文件,该文件可能有也可能没有一个名为<Popular>
的元素元素<EName>
的例子:
<Info>
<Enterprise>
<EName>
<Legal>Cool company</Legal>
</EName>
</Enterprise>
<Enterprise>
<EName>
<Legal>Cool company2</Legal>
<Popular>The company 2</Popular>
</EName>
</Enterprise>
</Info>
我使用scala缩放xml,像这样:
val Info = NoNamespaceQName("Info")
val Enterprise = NoNamespaceQName("Enterprise")
val EName = NoNamespaceQName("EName")
val Legal = NoNamespaceQName("Legal")
val Popular = NoNamespaceQName("Popular")
val EnterprisePath = List(Info, Enterprise)
val itr = iterate(EnterprisePath, xml)
for {
enterprise <- itr
enterpriseName <- enterprise * EName * Legal
enterprisePopularName <- enterprise * EName * Popular
} {
// Do fun stuff
Logger.info("enterprise: "+enterpriseName + " "+enterprisePopularName)
}
当Popular元素不存在时,不会执行for语句,也不会执行yield语句。
我想首先检查元素,如果Popular元素为空,则将enterprisePopularName设置为空字符串
类似:
<- if((enterprise * EName * Popular)) enterprise * EName * Popular else ""
但是我想不出来。我想这是因为我是个scala新手。
谓语回答将工作,但Seq
有一个很好的小方法称为padTo
,您可以使用它来确保序列中至少有n个值。它接受两个参数length: Int
和elem: B
,其中B
是Seq
包含的类型的子类型。所以在你的例子中应该是:
for {
enterprise <- itr
enterpriseName <- enterprise * EName * Legal
enterprisePopularName <- (enterprise * EName * Popular).padTo(1, reasonableDefaultValue)
}
警告:我不熟悉'scales',所以这里的细节可能是错误的。特别是,您可能会发现:
-
*
不返回Seq
-它可能返回Iterable
,在这种情况下,只需将Seq
替换为Iterable
,或者一些自定义集合,在这种情况下,您需要弄清楚如何翻译下面的方法。 - 可能,返回的序列类型是
Seq[Node]
或类似的,而不是Seq[String]
-您需要将默认值包装为节点,或者在应用默认值之前转换序列(使用.map(_.toString)
)。
我假设这里*
返回某种序列(Scala的Seq
)。我们需要的是一个接受Seq
和默认值的方法,如果Seq
为空,则产生默认值。请注意,这只是编写Option
的orElse
或getOrElse
方法的等价物的情况。
我们可以这样做:
def orIfEmpty[A](xs : Seq[A], default : A) : Seq[A] =
if (xs.isEmpty) Seq(default) else xs
现在我们可以在推导式中使用:
enterprisePopularName <- orIfEmpty(enterprise * EName * Popular, "")