Coder Social home page Coder Social logo

geirolz / advxml Goto Github PK

View Code? Open in Web Editor NEW
60.0 4.0 9.0 1.11 MB

A lightweight, simple and functional DSL library to work with XML in Scala with Cats

Home Page: https://geirolz.github.io/advxml

License: Apache License 2.0

Scala 99.94% Shell 0.06%
scala xml scala-xml lightweight functional scala-library library functional-programming cats dsl

advxml's Introduction

Advxml

Build Status codecov Codacy Badge Sonatype Nexus (Releases) javadoc.io Scala Steward badge GitHub license

⚠️ Please, have a look to the new WIP project cats-xml ⚠️

A lightweight, simple and functional library DSL to work with XML in Scala using native scala xml library and cats core.

How to import

Advxml supports 2.13 and 3

Sbt

  libraryDependencies ++= Seq(
    "com.github.geirolz" %% "advxml-core" % "2.5.0",
    "com.github.geirolz" %% "advxml-xpath" % "2.5.0" //optional, for xpath support
  )

Structure

The idea behind this library is offer a fluent syntax to edit and read xml.

Features:

Contributors

advxml's People

Contributors

argast avatar danslapman avatar dcsobral avatar dependabot[bot] avatar geirolz avatar liff avatar mergify[bot] avatar pawelkaczor avatar scala-steward avatar scala-steward-geirolz[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

advxml's Issues

XPath support

AS: User
IW: Convert XPath string into XmlZoom instance
So: We provides a method into XmlZoom to create an XmlZoom instance given the XPath string.

The methods will have the following signature:

def fromXPath(value: String) : F[XmlZoom]

The methods will be placed into XmlZoom companion's object.

Document a Nested XML to Model and vice versa

Would be really nice to have an Example where a nested XML is converted to model and vice versa. Reading the docs it seems simple to convert a simple XML to model.

e.g. how to convert nested XML example from docs to model ?

case class Person(name: String, surname: String, age: Option[Int], cars: Seq[Car], pronouns: Option[Seq[String]])
case class Car(brand: String, price: String)

Transformer engine apply transformation only on the first NodeSeq that match the XmlZoom

XmlRule transform engine doesn't work as expected when there are multiple NodeSeq that match XmlZoom actions.
The transformation is applied only on the firt NodeSeq that match.

val doc = <foo>
    <bar />
    <bar />
    <bar />
</foo>

val result : NodeSeq = doc.transform[Try](root.bar ==> SetAttrs(k"T" := 10)).get()

/*
* Expected
* <foo>
*    <bar T="10" />
*    <bar T="10" />
*    <bar T="10" />
* </foo>
*
* Actual
* <foo>
*    <bar T="10" />
*    <bar />
*    <bar />
* </foo>
*/

Transform existing XML

With the following structure

<SomeFields>
  <ABC>111</ABC>
</SomeFields>

SomeFields is my root node.

  1. What rule allows me to add a child node to SomeFields
    e.g.
<SomeFields>
  <ABC>111</ABC>
  <DEF>222</DEF>
</SomeFields>
  1. What rule allows me to edit a child node
<SomeFields>
  <ABC>444</ABC>
  <DEF>222</DEF>
</SomeFields>

This would be useful info for your documentation. Thanks in advance!

Coverage 100%

Missing tests:

  • Xml Traverser Syntax
  • Xml Filter instances

SBT compatibility error

Try to import with this
"com.github.geirolz" %% "advxml-core" % "2.4.0"

using scala 2.13.6 getting all the time a resolving error:

[error] (gui / update) found version conflict(s) in library dependencies; some are suspected to be binary incompatible:
[error]
[error] 	* org.scala-lang.modules:scala-xml_2.12:2.0.1 (early-semver) is selected over {1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.0.6}
[error] 	    +- com.github.geirolz:advxml-core_2.12:2.4.0          (depends on 2.0.1)
[error] 	    +- org.scala-lang:scala-compiler:2.12.14              (depends on 1.0.6)
[error] 	    +- com.typesafe.play:twirl-api_2.12:1.5.1             (depends on 1.2.0)
[error] 	    +- com.typesafe.play:play-ws-standalone-xml_2.12:2.1.3 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-scaladsl-cluster_2.12:1.6.5 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-persistence-jdbc-core_2.12:1.6.5 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-persistence-core_2.12:1.6.5 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-cluster-core_2.12:1.6.5  (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-api_2.12:1.6.5           (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-akka-management-core_2.12:1.6.5 (depends on 1.2.0)
[error]
[error]
[error] this can be overridden using libraryDependencySchemes or evictionErrorLevel
[error] (gui / ssExtractDependencies) found version conflict(s) in library dependencies; some are suspected to be binary incompatible:
[error]
[error] 	* org.scala-lang.modules:scala-xml_2.12:2.0.1 (early-semver) is selected over {1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.2.0, 1.0.6}
[error] 	    +- com.github.geirolz:advxml-core_2.12:2.4.0          (depends on 2.0.1)
[error] 	    +- org.scala-lang:scala-compiler:2.12.14              (depends on 1.0.6)
[error] 	    +- com.typesafe.play:twirl-api_2.12:1.5.1             (depends on 1.2.0)
[error] 	    +- com.typesafe.play:play-ws-standalone-xml_2.12:2.1.3 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-scaladsl-cluster_2.12:1.6.5 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-persistence-jdbc-core_2.12:1.6.5 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-persistence-core_2.12:1.6.5 (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-cluster-core_2.12:1.6.5  (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-api_2.12:1.6.5           (depends on 1.2.0)
[error] 	    +- com.lightbend.lagom:lagom-akka-management-core_2.12:1.6.5 (depends on 1.2.0)

do you have any idea to solve it?

Thank you

Nodes with the same value are mixed up

Hi!
I'm having a weird issue with targeting nodes that I want to replace, given the following snippet:

import scala.xml._
import advxml.syntax.traverse.try_._
import advxml.syntax.transform._
import advxml.instances.transform._
import scala.util._
import cats.implicits._

val doc = XML.loadString("""
<charts>
  <chart>
    <title>chart-0</title>
    <entries>
      <entry idx="0">
        <v>13</v>
      </entry>
    </entries>
  </chart>
  <chart>
    <title>chart-1</title>
    <entries>
      <entry idx="0">
        <v>12</v>
      </entry>
    </entries>
  </chart>  
</charts>
""")

def toEntries(root: NodeSeq): NodeSeq = (root \ "chart" filter hasImmediateChild("title", text(_ == "chart-1"))) \ "entries"

val rule = $(r => (toEntries(r) \ "entry" filter attrs("idx" -> (_ == "0"))) \ "v" ) ==> Replace(_ => <v>11</v>) 

val result: Try[NodeSeq] = doc.transform[Try](rule)

println(result.toOption.get)

It will output this:

<charts>
   <chart>
      <title>chart-0</title>
      <entries>
         <entry idx="0">
            <v>13</v>
         </entry>
      </entries>
   </chart>
   <chart>
      <title>chart-1</title>
      <entries>
         <entry idx="0">
            <v>11</v>
         </entry>
      </entries>
   </chart>
</charts>

https://scastie.scala-lang.org/JRM25U76S6yXpcIV6ZuDug
It correctly found entries of a chart which has chart-1 as a title and then replaced it.

But as soon as I make the original values to be the same number:

val doc = XML.loadString("""
<charts>
  <chart>
    <title>chart-0</title>
    <entries>
      <entry idx="0">
        <v>12</v>
      </entry>
    </entries>
  </chart>
  <chart>
    <title>chart-1</title>
    <entries>
      <entry idx="0">
        <v>12</v>
      </entry>
    </entries>
  </chart>  
</charts>
""")

it will replace the entry under chart-0, not chart-1 as expected:

<charts>
   <chart>
      <title>chart-0</title>
      <entries>
         <entry idx="0">
            <v>11</v>
         </entry>
      </entries>
   </chart>
   <chart>
      <title>chart-1</title>
      <entries>
         <entry idx="0">
            <v>12</v>
         </entry>
      </entries>
   </chart>
</charts>

https://scastie.scala-lang.org/KBkU87D6T4GhNlkDq3rWjQ

Looks like it's finding the element first, so in this case <v>12</v> and then using it for replacement, so if you have 2 identical elements bu with different paths it will replace the first one.

Or maybe I'm not using it correctly?
By they way, apart from this issue the library is a joy to use, thanks!

XmlRules should be composable

It should be possible to compose XmlRules with each other using following composition operators:

  • andThen - if first rule succeeds the second rule is applied
  • orElse - if first rule fails the second rule is applied

Currently it is not possible to compose rules. Instead andThen composition operator is implied when a list of XmlRules is provided to the the tranform method.

Use case description

Having a structure A.B I want to add an attribute to an existing B or, if the B is not found, I want to create new B under A.

To implement this scenario I would need to implement a rule using orElse combinator:

$.B.find(attrs(k"name" === "someName")) ==> SetAttr(_ => ...) orElse $ ==> Append(<B ....../>)

Rename Master with Main

Rename the master with main, just to avoid issue when some settings are copied from other repos

Change project dirs structure

Should create a modules folder that contains multiple modules(core, macros, etc..).
In order to do that build.sbt file should support multiple sub-modules.

Improve documentation

AS: Users
IW: Have more documentation about Advxml features with examples
SO: We can create more markdown files, one for each feature.

Features:

  • Xml Transformer
  • Xml Traverser
  • Xml Converter
  • Xml Normalizer

Cannot resolve symbol syntax

v0.1.6
import com.github.geirolz.advxml
//Advxml imports
import advxml.transform.XmlRule
//Supply $ and ==> syntax
import advxml.syntax.transform._
//Supply Append class
import advxml.instances.transform._

compiler throws error for line advxml.syntax.transform._ cannot resolve symbol syntax.

Also the first import is not documented but is required in order for the subsequent lines to compile.

Root transformation

AS: User
IW: To edit the root document easily
SO: I can provide a static no zoom action named "root".

Example

val doc : Elem = XML.loadString(s"<$fieldName>$fieldValue</$fieldName>")
val result: Try[NodeSeq] = xml.transform[Try](root ==> Append(doc))

Optional XmlRule that doesn't break the transformation

AS user
IW to define an XmlRule that doesn't break the transformation process if target is missing or if it fails
SO we can create a system to define mandatory or not an XmlRule.

We can define a new type OptionalXmlRule and creare an hierarchy with sealed trait BaseXmlRule. Current type XmlRule will inherit from BaseXmlRule and it will mantain his name even if a better name should be MandatoryXmlRule, maybe we can use a type alias.

At this point transformer engine will process all rules pattern matching hover them following the right behavior.

API Syntax proposal

sealed trait BaseXmlRule
case class MandatoryXmlRule extends BaseXmlRule
case class OptionalXmlRule extends BaseXmlRule

type XmlRule = MandatoryXmlRule

val xmlrule : XmlRule = root.missing.node => Append(<foo />)
val optXmlRule : OptionalXmlRule = rule.optional
val mandatoryXmlRule : MandatoryXmlRule = optXmlRule.mandatory

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.