redundent / kotlin-xml-builder

A lightweight type safe builder to build xml documents in Kotlin
Apache License 2.0
155 stars 19 forks source link

Feature Request: Generate typesafe builder from xml schema #2

Closed juangamnik closed 6 years ago

juangamnik commented 6 years ago

I don't know whether I am right here, but a cool addition to this project would be, if it was possible to generate typesafe builders from a xml schema file (like this: https://kotlinlang.org/docs/reference/type-safe-builders.html). This would make it possible to generate both:

  1. a type-safe builder dsl for html/xslt/...
  2. binding classes for reading in html/xslt/... into a "meta model"

What do you think?

redundent commented 6 years ago

Just want to make sure I'm understanding you correctly. Essentially some way to generate the classes/functions from an xsd, kind of like what xjc can do except specially tailored to this library instead of random classes? Do I have that right?

juangamnik commented 6 years ago

More or less, yes 😬. The difference to xjc would be, that the outcome of such a generation would be type safe builders (I would call it an internal Kotlin DSL).

So yes, it would be an internal DSL generator for XML Schema. The disadvantage of xjc is, that the classes can be used wonderfully to read in XML and then work with it, but it is cumbersome to create new XML with it.

The same would be great for JSON Schema / OpenAPI / Swagger, but I think this is the wrong project for this, isn't it? 😄

redundent commented 6 years ago

Totally agree about xjc. Can be a pain to work with.

I like the idea behind this and it could be interesting to do some fancy code generation with the xsd. One glaring problem that I can see right now with the code in its current form is there is no xsd validation or any sort of ordering of the nodes. Whichever node is added first, it will be at the top. That could very easily break the xsd contract.

I'll see what I can get going with this. Thanks for the suggestion.

juangamnik commented 6 years ago

Sure, there will be always dark spots which cannot be checked by the type checker, but have to be checked at runtime (e.g. during creation of an instance of the meta model, i.e., before rendering/serializing or doing other stuff). Another dark spot will be, that dynamically created child’s of a node may be checkable for conformance only at runtime, too (e.g. if the xsd contains a max-occurrence).

But it will be much better than xjc which has this dark spot issue either.

Or did I get your point wrong?

Thank you very much for going into this. If you need some help I would volunteer 😉. I hope I will find enough time...

juangamnik commented 6 years ago

Whichever node is added first, it will be at the top. That could very easily break the xsd contract.

If there is a mandatory order of nodes defined in the xsd, the generator can add corresponding methods, that will handle the ordering, but not present in the resulting output/meta model:

someParent {
  // This will not be part of the output, but maps type of 
  // node to correct position on its parents child axis.
  first {
    childAtFirstPos {}
  }
  // The wrong order is no problem at all, the result will be schema conform
  third { /* ... */}
  second { /* ... */ }
}
juangamnik commented 6 years ago

Alternatively, a childs (extension) function with named parameters could be added, iff there is an ordering on the child:

someParent(attr1 = "xy", attr2 = 123) {
  childs(
    first = firstChild { /* ... */),
    second = secondChild { /* ... */ }
  )
}
redundent commented 6 years ago

I think I found an elegant way to do it, that I kind of stole from XJC/JAXB.

@XmlType(childOrder = ["firstChild", "secondChild"])
class MyXmlType {}

Then just use the annotation values to determine the correct order to build the xml. Seems to work. Just need to have the generator add that to the output. Classes will be generated just to have a place to put the DSL methods/attributes on and hold the node correct ordering.

juangamnik commented 6 years ago

Ah ok, you do it the other way around: instead of enforcing the user to respect the child order, your code will respect the order, even if the order in the code is wrong. Do I understand you correctly?

juangamnik commented 6 years ago

So it is happening? You‘ll add support for this?

It would be so great, if one could just generate a DSL for XML Schema and XSLT and then write XSLT code (with XML Schema elements needed e.g. for Stylesheet parameter definitions) with embedded XML-output (using your current syntax if there is no schema or cool new stuff if there is a Schema) all in Kotlin... 🤯🤤

juangamnik commented 6 years ago

Again: if you need support, tell me.

redundent commented 6 years ago

Yes, I'm planning on doing it. I just need to find the time to actually code it. The generation based on child ordering works so now I just need to generate the code from the XSD, which shouldn't be too bad.

redundent commented 6 years ago

I just pushed the code for this and uploaded the jar to use it. There are some usage details at kotlin-xml-dsl-generator.

I'm not guaranteeing it to be perfect but it was working pretty we will my testing. Let me know how you get on with it.

juangamnik commented 6 years ago

Nice! I'll try it out as fast as I can and give feedback

redundent commented 6 years ago

Just FYI, I'm currently tweaking the generation of the classes to add command line parameter to allow an option to use member functions for the child elements instead of extension methods. Doesn't really have a whole lot of effect on the kotlin side but it makes calling it from java (not sure if anyone would really want to do that but...) a little cleaner.

redundent commented 6 years ago

Closing this as it's been idle for nearly 7 months