Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/geirolz/cats-xml
A functional library to work with XML in Scala using Cats.
https://github.com/geirolz/cats-xml
cats decoding encoding fp functional-programming scala xml
Last synced: 6 days ago
JSON representation
A functional library to work with XML in Scala using Cats.
- Host: GitHub
- URL: https://github.com/geirolz/cats-xml
- Owner: geirolz
- License: apache-2.0
- Created: 2022-03-15T15:34:59.000Z (over 2 years ago)
- Default Branch: main
- Last Pushed: 2024-10-24T10:56:18.000Z (13 days ago)
- Last Synced: 2024-10-25T09:38:15.490Z (12 days ago)
- Topics: cats, decoding, encoding, fp, functional-programming, scala, xml
- Language: Scala
- Homepage: https://geirolz.github.io/cats-xml/
- Size: 594 KB
- Stars: 27
- Watchers: 2
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# cats-xml
[![Build Status](https://github.com/geirolz/cats-xml/actions/workflows/cicd.yml/badge.svg)](https://github.com/geirolz/cats-xml/actions)
[![codecov](https://img.shields.io/codecov/c/github/geirolz/cats-xml)](https://codecov.io/gh/geirolz/cats-xml)
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/3101ec45f0114ad0abde91181c8c238c)](https://www.codacy.com/gh/geirolz/cats-xml/dashboard?utm_source=github.com&utm_medium=referral&utm_content=geirolz/cats-xml&utm_campaign=Badge_Grade)
[![Sonatype Nexus (Releases)](https://img.shields.io/nexus/r/com.github.geirolz/cats-xml-core_2.13?server=https%3A%2F%2Foss.sonatype.org)](https://mvnrepository.com/artifact/com.github.geirolz/cats-xml-core)
[![javadoc.io](https://javadoc.io/badge2/com.github.geirolz/cats-xml-core_2.13/javadoc.io.svg)](https://javadoc.io/doc/com.github.geirolz/cats-xml-core_2.13)
[![Scala Steward badge](https://img.shields.io/badge/Scala_Steward-helping-blue.svg?style=flat&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAQCAMAAAARSr4IAAAAVFBMVEUAAACHjojlOy5NWlrKzcYRKjGFjIbp293YycuLa3pYY2LSqql4f3pCUFTgSjNodYRmcXUsPD/NTTbjRS+2jomhgnzNc223cGvZS0HaSD0XLjbaSjElhIr+AAAAAXRSTlMAQObYZgAAAHlJREFUCNdNyosOwyAIhWHAQS1Vt7a77/3fcxxdmv0xwmckutAR1nkm4ggbyEcg/wWmlGLDAA3oL50xi6fk5ffZ3E2E3QfZDCcCN2YtbEWZt+Drc6u6rlqv7Uk0LdKqqr5rk2UCRXOk0vmQKGfc94nOJyQjouF9H/wCc9gECEYfONoAAAAASUVORK5CYII=)](https://scala-steward.org)
[![GitHub license](https://img.shields.io/github/license/geirolz/cats-xml)](https://github.com/geirolz/cats-xml/blob/master/LICENSE)A functional library to work with XML in Scala using cats core.
```sbt
libraryDependencies += "com.github.geirolz" %% "cats-xml" % "0.0.18"
```This library is not production ready yet. There is a lot of work to do to complete it:
- [X] Macros to derive `Encoder` and `Decoder` for Scala 2
- [X] Reach a good code coverage with the tests (using munit) above 60%
- [X] Support XPath
- [X] `Decoder` and `Encoder` for primitives with error accumulating
- [X] Good error handling and messaging
- [X] Integration with standard scala xml library
- [X] Integration with cats-effect to load files effectfully
- [ ] Macros to derive `Encoder` and `Decoder` for Scala 3
- [ ] Performance benchmarks
- [ ] Integration with Tapir and Http4s
- [ ] Literal macros to check XML strings at compile timeContributions are more than welcome 💪
Please, drop a ⭐️ if you are interested in this project and you want to support it
## Modules
- [Effect](docs/compiled/effect.md)
- [Generic (scala 2 only so far)](docs/compiled/generic.md)
- [ScalaXml](docs/compiled/scalaxml.md)
- [XPath](docs/compiled/xpath.md)## Example
Given
```scala
case class Foo(
foo: Option[String],
bar: Int,
text: Boolean
)
```### Plain creation
```scala
import cats.xml.XmlNode
import cats.xml.implicits.*
import cats.implicits.*val optNode: Option[XmlNode] = None
// optNode: Option[XmlNode] = None
val node: XmlNode =
XmlNode("Wrapper")
.withAttrs(
"a" := 1,
"b" := "test",
"c" := Some(2),
"d" := None,
)
.withChildren(
XmlNode("Root").withChildren(
XmlNode.group(
XmlNode("A").withText(1),
XmlNode("B").withText("2"),
XmlNode("C").withText(Some(3)),
XmlNode("D").withText(None),
optNode.orXmlNull
)
)
)
// node: XmlNode =
//
// 1
// 2
// 3
//
//
//
```### Decoding
```scala
import cats.xml.codec.Decoder
import cats.xml.implicits.*
import cats.implicits.*val decoder: Decoder[Foo] =
Decoder.fromCursor(c =>
(
c.attr("name").as[Option[String]],
c.attr("bar").as[Int],
c.text.as[Boolean]
).mapN(Foo.apply)
)
```### Encoding
```scala
import cats.xml.XmlNode
import cats.xml.codec.Encoderval encoder: Encoder[Foo] = Encoder.of(t =>
XmlNode("Foo")
.withAttrs(
"foo" := t.foo.getOrElse("ERROR"),
"bar" := t.bar
)
.withText(t.text)
)
```### Navigating
```scala
import cats.xml.XmlNode
import cats.xml.cursor.Cursor
import cats.xml.cursor.FreeCursor
import cats.xml.implicits.*val node =
xml"""
1
2
3
"""
// node: XmlNode =
//
// 1
// 2
// 3
//
//val fooNode: Cursor.Result[XmlNode] = node.focus(_.root.foo)
// fooNode: Cursor.Result[XmlNode] = Right(value = 1)
val fooTextValue: FreeCursor.Result[Int] = node.focus(_.root.foo.text.as[Int])
// fooTextValue: FreeCursor.Result[Int] = Valid(a = 1)
```### Modifying
```scala
import cats.xml.XmlNode
import cats.xml.modifier.Modifier
import cats.xml.implicits.*val node = xml"""
1
"""
// node: XmlNode =
//
//
//
//
// 1
//
//
//
//
//val result: Modifier.Result[XmlNode] = node.modify(_.root.foo.baz.bar.value.modifyNode(_.withText(2)))
// result: Modifier.Result[XmlNode] = Right(
// value =
//
//
//
//
// 2
//
//
//
//
//
// )
```