0

使用 Scala,我有以下代码:

def insertRefIntoXml(ref: Int, entry: Node): Node = entry match {
    case <root>{ mainRoot @ _* }</root> 
        => <root>{ mainRoot.map(insertRefIntoXml ref  )}</root>
    case <here>{ contents }</here> => <here>{ ref }</here>
    case other @ _ => other

}

我想要做的是继续向下传递“ref”值,直到我到达here元素,然后将其交换。

这行不通。会怎样?

检查此链接以获取原始问题

4

2 回答 2

0

看看这是否适合你:

object TestXml {
  def main(args: Array[String]) {
    val xml = 
      <root>        
    <here>
      <dealID>foo</dealID>
    </here>        
  </root>

    println(insertRefIntoXml(2, xml))
  }

  def insertRefIntoXml(ref: Int, entry: Node): Node = {    
    def doInsertRef(n:Node):Node = {    
      n match {
        case <root>{ mainRoot @ _* }</root> => <root>{ mainRoot.map(doInsertRef)}</root>
        case <here><dealID>{ contents }</dealID></here> => <here><dealID>{ ref }</dealID></here>
        case other @ _ => other
      }       
    }
    doInsertRef(scala.xml.Utility.trim(entry))
  }
}

有几个问题。首先,为了以您想要的方式insertRefIntoXml在调用中使用map,它只需要一个 arg 而不是两个。为了解决这个问题,我创建了一个本地函数 def,然后ref通过闭包从那里获取值。你也可以像这样解决这个问题:

  def insertRefIntoXml(ref: Int, entry: Node): Node = {       
    entry match {
      case <root>{ mainRoot @ _* }</root> => <root>{ mainRoot.map(insertRefIntoXml(ref, _))}</root>
      case <here><dealID>{ contents }</dealID></here> => <here><dealID>{ ref }</dealID></here>
      case other @ _ => other
    }       
  }

然后这样称呼它:

insertRefIntoXml(2, scala.xml.Utility.trim(xml))

这让我想到了第二个问题。我正在修剪以便匹配语句正确匹配。当我运行代码时,我相信它会给出你想要的输出。

于 2013-07-18T13:28:13.863 回答
0

解决方案将是xml 树上的拉链结构。

Anti-XML项目曾经有过,但它似乎落后了,所以它只为 scala 2.9.1 提供

无论如何,这就是它的工作方式,以防万一您查看解决方案以获得一些灵感

object XMLTreeUpdate {
  import com.codecommit.antixml._
  import com.codecommit.antixml.Converter

  def insertRefIntoXml(ref: Int, entry: Node, selector: String): Node = {
    /* selects the node of interest, but with the 
     * structure around it to rebuild the original tree (this is a zipper)
     */
    val zipper = Group(entry) \\ selector

    //gets the zipper value and creates a modified copy
    val mod = zipper.head.copy(children = Group(Text(ref.toString)))

    /* updates the modified branch in the zipper and unwinds it
     * then removes the zipper structure and gets the actual result
     */
    zipper.updated(0, mod).unselect.stripZipper.head
  }

  def testIt = {
    val entry = 
      <some>
        <inner>
          this is some content <here>n.d.</here>
          but not <special>here</special>
        </inner>
      </some>

    //converts to antixml node, which has a parallel api to scala.xml
    val antry = entry.convert

    val expected =
      <some>
        <inner>
          this is some content <here>10</here>
          but not <special>here</special>
        </inner>
      </some>

    val output = insertRefIntoXml(10, antry, "here")
    assert(expected.convert == output)
    output
  }
}
于 2013-07-18T22:39:40.863 回答