加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

有没有办法使用Scala的XML库执行XPath字符串查询?

发布时间:2020-12-16 09:02:26 所属栏目:安全 来源:网络整理
导读:给定一个 scala XML对象,我可以执行xpath字符串查询,例如“// entries [@ title =’scala’]”吗? 理想情况下,它会像: a b name ='n1' / b / a .xpath(“// b [@ name =’n1′]”) 我无法手动将所有xpath查询转换为scala的内部xpath-ish方法调用,因为我的
给定一个 scala XML对象,我可以执行xpath字符串查询,例如“// entries [@ title =’scala’]”吗?

理想情况下,它会像:

< a>< b name ='n1'>< / b>< / a> .xpath(“// b [@ name =’n1′]”)

我无法手动将所有xpath查询转换为scala的内部xpath-ish方法调用,因为我的程序将动态接受xpath查询.

另外,内置的java xml库非常冗长,所以我想避免它.

解决方法

您最好的选择是(并且始终是,甚至在 Java中)使用JDOM.我使用以下库对JDom进行了拉伸操作,以便更加友好地使用scala:

import org.jdom._
import org.jdom.xpath._
import scala.collection.JavaConversions
import java.util._
import scala.collection.Traversable


package pimp.org.jdom{
   object XMLNamespace{
      def apply(prefix:String,uri:String) = Namespace.getNamespace(prefix,uri)
      def unapply(x:Namespace) = Some( (x.getPrefix,x.getURI) )
   }
   object XMLElement{
      implicit def wrap(e:Element) = new XMLElement(e)
      def unapply(x:Element) = Some( (x.getName,x.getNamespace) )
   }
   class XMLElement(underlying:Element){
      def attributes:java.util.List[Attribute] =
         underlying.getAttributes.asInstanceOf[java.util.List[Attribute]]
      def children:java.util.List[Element] =
         underlying.getChildren.asInstanceOf[java.util.List[Element]]
      def children(name: String): java.util.List[Element] =
         underlying.getChildren(name).asInstanceOf[java.util.List[Element]]
      def children(name: String,ns: Namespace): java.util.List[Element] =
         underlying.getChildren(name,ns).asInstanceOf[java.util.List[Element]]
   }
}

package pimp.org.jdom.xpath{
   import pimp.org.jdom._

   //instances of these classes are not thread safe when xpath variables are used

   class SingleNodeQuery[NType](val expression:String)(implicit namespaces:Traversable[Namespace]=null){
      private val compiled=XPath.newInstance(expression)

      if (namespaces!=null){
         for ( ns <- namespaces ) compiled.addNamespace(ns.getPrefix,ns.getURI)
      }

      def apply(startFrom:Any,variables:(String,String)*)={
         variables.foreach{ x=> compiled.setVariable(x._1,x._2)}
         compiled.selectSingleNode(startFrom).asInstanceOf[NType]
      }
   }

   class NodesQuery[NType](val expression:String)(implicit namespaces:Traversable[Namespace]=null){
      private val compiled=XPath.newInstance(expression)

      if (namespaces!=null){
         for ( ns <- namespaces ) compiled.addNamespace(ns.getPrefix,x._2)}
         compiled.selectNodes(startFrom).asInstanceOf[java.util.List[NType]]
      }
   }

   class NumberValueQuery(val expression:String)(implicit namespaces:Traversable[Namespace]=null){
      private val compiled=XPath.newInstance(expression)

      if (namespaces!=null){
         for ( ns <- namespaces ) compiled.addNamespace(ns.getPrefix,x._2)}
         compiled.numberValueOf(startFrom).intValue
      }
   }

   class ValueQuery(val expression:String)(implicit namespaces:Traversable[Namespace]=null){
      private val compiled=XPath.newInstance(expression)

      if (namespaces!=null){
         for ( ns <- namespaces ) compiled.addNamespace(ns.getPrefix,x._2)}
         compiled.valueOf(startFrom)
      }
   }

}

我写这篇文章时的想法是,通常,您希望提前编译每个XPath查询(以便可以多次重复使用),并且您希望在指定的位置指定查询返回的类型查询的文本(不像JDOM的XPath类那样选择在执行时调用的四种方法之一).

命名空间应该隐式传递(因此您可以指定它们一次然后忘记它们),并且XPath变量绑定应该在查询时可用.

您可以像这样使用库:(可以推断显式类型注释 – 我将它们包含在内仅用于说明.)

val S = XMLNamespace("s","http://www.nist.gov/speech/atlas")
val XLink = XMLNamespace("xlink","http://www.w3.org/1999/xlink")
implicit val xmlns= List(S,XLink)

private val anchorQuery=new ValueQuery("s:AnchorRef[@role=$role]/@xlink:href")

val start:String=anchorQuery(region,"role"->"start")
val end:String=anchorQuery(region,"role"->"end")

//or

private val annotationQuery=new NodesQuery[Element]("/s:Corpus/s:Analysis/s:AnnotationSet/s:Annotation")

for(annotation:Element <- annotationQuery(doc)) {
  //do something with it
}

我想我应该想出一些方法向公众发布这个.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读