Как построить NodeSeq программно? - PullRequest
1 голос
/ 13 февраля 2011

У меня есть такой NodeSeq

val article_template =
 <div>
      <div class="title"></div>
      <div class="content"></div>
      <!-- some other markups don't know -->
 </div>

Я хочу создать эту структуру для каждой статьи в списке (определяется как val articleList), в результате чего:

 <div>
      <div class="title">title a</div>
      <div class="content">content a</div>
      <!-- some other markups don't know -->
 </div>
 <div>
      <div class="title">title b</div>
      <div class="content">content b</div>
      <!-- some other markups don't know -->
 </div>
...

Обновлено :

Обратите внимание на <!-- some other markups don't know --> часть, поэтому я не могу использовать буквальный синтаксис XML для его создания. Мне нужен список модифицированных article_template с соответствующей информацией статьи.

Ответы [ 5 ]

3 голосов
/ 08 августа 2012

Это что-то Лифт действительно хорошо для

import net.liftweb.util.Helpers._ 

case class Article( title: String, content: String )

val articles = List(
    Article("title a","content a"),
    Article("title b","content b")
)  

val snipet =
"article *" #> articles.map { article =>
    "header h1 *" #> article.title &
    ".content *" #> article.content
}

val article_template =
<article>
    <header>
        <h1>Title</h1>
    </header>
    <section class="content">
        Content
    </section>
</article>

snipet( article_template )
3 голосов
/ 13 февраля 2011

См. Scala.xml.transform._ и соответствующие вопросы о переполнении стека.

Вероятно, это будет выглядеть примерно так:

import scala.xml._
import transform._

case class Article( title: String, content: String )

val articleList = List(
    Article("title 1","content 1"),
    Article("title 2","content 2")
)

class TransformArticle(title: String, content: String) extends RewriteRule {
  override def transform(n: Node): Seq[Node] = n match {
    case div @ <div/> => div match {
        case elem: Elem if elem \ "@class" contains Text("title") =>
            elem copy (child = Text(title))
        case elem: Elem if elem \ "@class" contains Text("content") =>
            elem copy (child = Text(content))
        case other => other
    }
    case other => other
  }
}

val article_template =
 <div>
      <div class="title"></div>
      <div class="content"></div>
      <!-- some other markups don't know -->
 </div>

Group(
    articleList.flatMap( article => {
        new RuleTransformer(new TransformArticle(article.title, article.content)) transform article_template
    })
)

1 голос
/ 13 февраля 2011

Предполагая, что Article определено примерно так:

case class Article(title: String, content: String)

и articleList как:

val articleList = List(
  Article("title a","content a"),
  Article("title b", "content b"))

Вы можете создать фрагмент XML с помощью:

val xml: scala.xml.NodeSeq = articleList map { article => 
  <div>
    <div class="title">{article.title}</div>
    <div class="content">{article.content}</div>
  </div>
}
1 голос
/ 13 февраля 2011

Вы можете использовать Group для группировки элементов XML. В XML-литерале это будет выглядеть так:

val xml =
  <xml:group>
    <div>
      <div class="title">title a</div>
      <div class="content">content a</div>
    </div>
    <div>
      <div class="title">title b</div>
      <div class="content">content b</div>
    </div>
  </xml:group> 

Обновление

Вы можете создавать XML динамически следующим образом:

case class Article(title: String, content: String)
val articles = List(Article("A1", "A1 content"), Article("A2", "A2 content"))

val xml =
  <xml:group>{articles map { a =>
    <div>
      <div class="title">{a title}</div>
      <div class="content">{a content}</div>
    </div>
  }}</xml:group>

Обновление 1

Вот еще один вариант с использованием шаблона. Шаблон это просто функция, которая возвращает XML. В этом случае я использую карри для того, чтобы создать список шаблонов для каждой статьи (для этого еще нужно кое-что предоставить):

case class Article(title: String, content: String)
val articles = List(Article("A1", "A1 content"), Article("A2", "A2 content"))

def articleTemplate[T](article: Article)(stuff: T) =
  <div>
    <div class="title">{article title}</div>
    <div class="content">{article content}</div>

    <div class="stuff">{stuff}</div>
  </div>

val allArticles = articles map articleTemplate

val allArticlesWithStuff: NodeSeq =
  allArticles.zipWithIndex map {case (f, i) => f(i)} 
0 голосов
/ 13 февраля 2011

Используйте flatmap, чтобы сложить их вместе следующим образом:

val xml: NodeSeq = List("Test", "Something", "Yo").flatMap(s => <a>{s}</a>)
  • Конечно, со статьями вместо строк

Обновление : Работаеттакже с соответствием

val xml: NodeSeq = List("Test", "Something", "Yo", 1).flatMap{
  case s: String => <string>{s}</string>
  case i: Int => <int>{i}</int>
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...