замена значений xml программно с помощью scala - PullRequest
4 голосов
/ 25 октября 2010

Я пишу инструмент для обновления некоторых xml-файлов (в данном случае pom.xml) с помощью scala, потому что усилия, которые потребуются в java, значительно выше, чем (в теории), в сравнении с scala. Я могу просто разобрать xml-файл, но мне нужно заменить узлы в существующем xml и переписать результат. например:

<dependency>
    <groupId>foo</groupId>
    <artifactId>bar</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

Итак, я хочу найти все такие узлы и заменить их на:

<dependency>
    <groupId>foo</groupId>
    <artifactId>bar</artifactId>
    <version>1.0</version> <!-- notice the lack of -SNAPSHOT here -->
</dependency>

Итак, я могу достаточно просто получить все узлы версий, но как заменить их на нужный мне узел?

// document is already defined as the head of the xml file
nodes = for (node <- document \\ "version"; if (node.text.contains("SNAPSHOT"))) yeild node

тогда я хочу сделать что-то вроде:

for (node <- nodes) {
    node.text = node.text.split("-")(0)
}

, который не работает, потому что узел неизменен. Я посмотрел на метод копирования для узла, но он не включает text в качестве параметра.

Ответы [ 3 ]

12 голосов
/ 26 октября 2010

Вы действительно должны взглянуть на другие вопросы по переполнению стека об изменении XML.Посмотрите на "Связанные" ссылки справа.

Здесь:

scala> <dependency>
     |     <groupId>foo</groupId>
     |     <artifactId>bar</artifactId>
     |     <version>1.0-SNAPSHOT</version>
     | </dependency>
res0: scala.xml.Elem =
<dependency>
    <groupId>foo</groupId>
    <artifactId>bar</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>

scala> new scala.xml.transform.RewriteRule {
     |   override def transform(n: Node): Seq[Node] = n match {
     |     case <version>{v}</version> if v.text contains "SNAPSHOT" => <version>{v.text.split("-")(0)}</version>
     |     case elem: Elem => elem copy (child = elem.child flatMap (this transform))
     |     case other => other
     |   }
     | } transform res0
res9: Seq[scala.xml.Node] =
<dependency>
    <groupId>foo</groupId>
    <artifactId>bar</artifactId>
    <version>1.0</version>
</dependency>
2 голосов
/ 26 октября 2010

Текст представляется как Node внутри узла Element s. Так что немного функциональной рекурсии позволит вам сделать глубокое копирование и фильтр:

def deepCopy(node:Node) : Node = node match {
  case e : Elem => e.copy(child = this.child.toSeq.map(deepCopy))
  case t : Text => new Text(t.text.split("-").head)
  case x => x
}

отказ от ответственности: этот код не был проверен на ошибки

0 голосов
/ 01 июля 2014

Использование Преобразования Scuery CSS3 от Scalate и scala.xml.Elem#copy:

val xml =
  <dependency>
    <version>1.0-SNAPSHOT</version>
    <version>2.0</version>
  </dependency>

new Transformer {
  $("dependency > version") { node =>
    node.asInstanceOf[Elem].copy(child = Text(node.text.stripSuffix("-SNAPSHOT")))
  }
}.apply(xml)

выходы

NodeSeq(<dependency><version>1.0</version><version>2.0</version></dependency>)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...