3

私のscalaコードは現在、xmlファイルのセクション全体を、追加している新しいタグに置き換えることになります。タグを ClientConfig の子として一度だけ追加したいのですが、このセクションにあるすべてのタグをそれ自体に置き換えます。

val data = XML.load(file)
val p = new XMLPrettyPrinter(2)
val tryingtoAdd = addNewEntry(data,host,env)
p.write(tryingtoAdd)(System.out)

ここで、host=bob と env=flat は以前に定義されており、addNewEntry は次のように定義されています。

 private def isCorrectLocation(parent: Elem, node: Elem, host: String): Boolean = {
    parent.label == "ClientConfig" && node.label == "host"
  }

  def addNewEntry(elem:Elem, host: String, env: String): Elem ={
    val toAdd = <host name={host} env={env} />
    def addNew(current: Elem): Elem = current.copy(
      child = current.child.map {
        case e: Elem if isCorrectLocation(current, e, host) ⇒ toAdd
        case e: Elem ⇒ addNew(e)
        case other ⇒ other
      }
    )
    addNew(elem)
  }

それが生成するxmlは

<ClientConfig>
    <host name="bob" env="flat"/>
    <host name="bob" env="flat"/>
    <host name="bob" env="flat"/>
    <host name="bob" env="flat"/>
</ClientConfig>

代わりに、最後の3つの子がすでにファイルに存在していたこのような ClientConfig の単一の子として追加したい

<ClientConfig>
    <host name="bob" env="flat"/>
    <host name="george" env="flat"/>
    <host name="alice" env="flat"/>
    <host name="bernice" env="flat"/>
</ClientConfig>

私は何をしますか?たとえば、pythonには単純な挿入メソッドがあります

4

2 に答える 2

2

あなたの場合、パターンマッチが

case e: Elem if isCorrectLocation(current, e, host) => toAdd

toAdd メソッドは、渡したホスト env を使用しますaddNewEntry(data, host, env)。ホストはbob、envはフラット。したがって、toAdd は常に を返し<host name="bob" env="flat"/>ます。

次のような client.xml があるとします。

   <Root>
     <ServerConfig>
       <host name="allen" env="flat"/>
     </ServerConfig>
     <ClientConfig>
       <host name="george" env="flat"/>
       <host name="alice" env="flat"/>
       <host name="bernice" env="flat"/>
    </ClientConfig>
   </Root>

次のコードは、私がそれを成し遂げようとする方法です。

    def toBeAddedEntry(name: String, env: String) = <host name={ name } env={ env } />
    def addNewEntry(originalXML: Elem, name: String, env: String) = {
      originalXML match {
         case e @ Elem(_, _, _, _, configs @ _*) => {
            val changedNodes = configs.map {
                case <ClientConfig>{ innerConfigs @ _* }</ClientConfig> => {
                    <ClientConfig> { toBeAddedEntry(name, env) ++ innerConfigs }</ClientConfig>
                }
                case other => other
             }
            e.copy(child = changedNodes)
         }
         case _ => originalXML
     }
   }   

    val originalXML = XML.load("client.xml")
    val printer = new scala.xml.PrettyPrinter(80,5)
    println(printer.format(addNewEntry(originalXML, "bob", "flat")))


    // result
    <Root>
      <ServerConfig>
        <host env="flat" name="allen"/>
     </ServerConfig>
     <ClientConfig>
       <host name="bob" env="flat"/>
       <host env="flat" name="george"/>
       <host env="flat" name="alice"/>
       <host env="flat" name="bernice"/>
    </ClientConfig>
   </Root>

さらに、その過程であることに気が付きます。XML.load は実際には属性の順序を逆にします。問題の解決には関係ないかもしれませんが、必要な場合に備えてここに追加してください。

于 2015-08-01T01:42:33.343 に答える