1

これは私の前の質問のフォローアップです

次のような XML を検証する必要があるとします。

<a><a1>xxx<a1/><a2>yyy</a2><a3>zzz</a3></a>

ルート要素にラベルがあり、この順序でa<a1>xxx</a1>、があることを確認する必要があります。<a2>yyy</a2><a3>zzz</a3>

List[String]エラーを収集し、次のような単一の XML 要素を検証する関数を定義するために使用したいと思います。

type ValidateSingleElement = Elem => List[String]

これで、特定の XML 要素のラベル、テキスト、および属性を検証する関数を作成できるようになりました。

val label : String => ValidateSingleElement = ...
val text  : String => ValidateSingleElement = ...
val attr  : (String, String) => ValidateSingleElement = ...

はモノイドである|+|ため、これらの関数を構成できます。ValidateSingleElement

val a1 = label("a1") |+| text("xxx") // validate both label and text

ここで、特定の要素の子を検証する関数が必要です。このような関数を作成するには、要素 のシーケンスを検証する別の関数が必要です

val children: ValidateElements => ValidateSingleElement = ...

ValidateElements次のように定義されます。

type ValidateElements = List[Elem] => Writer[List[String], List[Elem]]

一連の要素をトラバースしながらエラーを収集するためにList[String]andモナドを使用しています。Writer

これで、特定の要素の子を検証する関数を作成できます。

val children: ValidateElements => ValidateSingleElement = 
  validateElements => {e =>
    val kids = e.child collect {case e:Elem => e}
    val writer = validateElements(kids.toList)
    writer.written
  }

...そして、シーケンスの最初の要素を検証します:

 val child: ValidateSingleElement => ValidateElements = validate => {
   _ match {
     case e:es => Writer(validate(e), es)
     case _    => Writer(List("Unexpected end of input"), Nil)
   }
 }

ValidateElements最後に、次のように再定義できますKleisli

type ErrorsWriter[A]  = Writer[List[String], A]
type ValidateElements = Kliesli[ErrorsWriter, List[Elem], List[Elem]]

...そして、関数の代わりにchildを返すように書き直します。Kleisli

childchildren私が書くことができる両方を考えると、a上記の XML の検証関数:

val a1 = label("a1") |+| text("xxx")
val a2 = label("a2") |+| text("yyy")
val a3 = label("a3") |+| text("zzz")
val a  = label("a")  |+| children(child(a1) >=> child(a2) >=> child(a3))

それは理にかなっていますか?このデザインをどのように修正/拡張しますか?

4

1 に答える 1

1

ほとんどの場合、XML ドキュメントを検証するだけではなく、そこから何らかの意味のあるビジネス オブジェクトを作成したいのですが、コードではそれが許可されていないようです。Play の型クラス ベースの Json ライブラリは、これを行う方法の良いモデルだと思います。Readsオブジェクトを定義できます。ここで、 aReads[A]は本質的にJsValue => Either[Errors, A]です。これらは、ライブラリに同梱されている一連のコンビネータと柔軟に組み合わせることができます。

于 2016-01-31T01:37:30.957 に答える