This post has been written using material developed in JetBrains MPS 3.3.5. The example project can be found at DSLFoundry’s MPS example github repository under StructureDumpToXML. It is recommended to have this project opened while going through this howto.
Suppose you want to dump a model to some simple XML format without wanting to write a generator or wanting any specific knowledge about the structure of the model. A use case for this could be that you don’t want to have to make changes in the generator for a simple XML dump, just because you change the structure. Now of course this can be solved using custom persistance, but let’s say you just want something quick and simple without having to deal with too much of the more complicated stuff like references. This howto shows such a simple case. So here we go:
An example model:
Let’s use the generator mechanism and the xml language from JetBrains to make an XML dump out of this:
- make a root mapping rule, by double clicking on the generator’s main, then click on root mapping rules and press enter:
- choose MyConcept in the input concept:
- import the xml language by pressing Ctrl+L+L (yes, you have to press L a second time) and then choosing it:
- stand on the template of the root mapping rule and press Alt+Enter to invoke the intention menu and choose New Root Template, then choose directly xml file:
and then:
- navigate to map_MyConcept by Ctrl + clicking it:
- add an XML element using the completion menu:
- call the element something (e.g. bla) and create a MAP_SRC macro which makes it possible to build any wild mapping construct you’d like:
and then:
- now go to the inspector of this MAP_SRC macro by clicking the macro and pressing ALT+2:
- go to the <none> part of the mapping func and then press Enter to create a mapping function:
- from this point on, you can type baseLanguage code, which is pretty much the same as typing java. We replace the XML element <bla></bla> with a new XmlElement node that we create, using some regular programming. See the next step first to see how to create the dumpStructure funciton so that you can call it here in the macro. The code you see is a combination of baseLanguage and smodel language. The MPS smodel language makes it possible to query a model and build nodes. For more information on this, see the MPS smodel reference:
- in the above piece of code, we use a piece of behavior that belongs to a helper aspect called StructureDumper. This code can be created by making a concept called structure helper and then making a new behavior for it:
- now we can type the code for the dumpStructure function. This is just a recursive function reading the model and dumping everything to XML. Note: in the statement mpsNode/.getProperties(), there is this strange notation mpsNode/. This is a so-called semantic downcast operation. It makes it possible to reach directly the java class that encode the node mpsNode (needed here for reflectively reaching its properties).
- since the XML language has a text generator and we hooked the transformation from our model to XML in a MAP_SRC macro of a generator, we have text generation. You can preview the text by right-clicking the model called myconcept in the StructureDumpToXML solution and selecting Preview Generated Text:
- and the text will look like this:
- note that nothing smart has been done yet with references. This is tricky, since we may get (even indirect) circular references.
This howto has demonstrated the use of MAP_SRC macro to do a dump of an arbitrary (at least for simple cases where it’s a tree) MPS model to an XML format of your own choosing. Feel free to extend and improve for your own needs. We may one day make a language that will just do this automatically.
If this post helped you, gave you ideas or has motivated you to help, please feel free to contact us on github.
Extra tips:
- if you need special characters properly escaped as XML entities in MPS 3.3.5, it is recommended to use mbeddr’s com.mbeddr.mpsutil.xml.fix language.
- you may need to use light quotations instead of the manually written code for node instantiations in the above described dump function (see JetBrains docsite on light quotations). The reason that you cannot use full quotations is, I think, because you may not have all the editors built before building behavior, which makes it impossible to have the editor to make a full quotation.
Would be nice to also be able to import it back. So far googling around I don’t see any good way of importing stuff like JSON or YAML or XML based solutions to MPS. Would you be kind enough to give any suggestions if you can think of any? I’m trying something very simple (import a DAG defined in a CSV)
Yes, as far as I know there is no generic XML language with import/export. It is not hard to make (especially if you have access to an XSD for your XML), but it seems nobody got to it yet.
You can import XML yourself, though, using a simple XML parser. The easiest way is to just create an intention on a concept where you want to import XML and then just write normal XML parse code (using DOM or SAX parser).
Another way is to put it below a button (e.g. the plaintextgen plugin (https://github.com/DSLFoundry/mps-plaintextgen) has a right-click action to paste unstructured text; to know how that entry point is made, see com.dslfoundry.plaintextgen/plugin/PasteUnstructuredText when you check out the code from plaintextgen).
Also, if you have access to the mbeddr platform (https://github.com/mbeddr/mbeddr.core) and/or MPS Extensions (https://github.com/JetBrains/MPS-extensions) plugins (for MPS 2018.1), there is an xmlimport plugin with an action called pasteAsXmlContent. I haven’t tried it yet, but you can find it here when you open the solutions or in the modules pool when you install the plugins: com.mbeddr.mpsutil.xmlimport/plugin/pasteAsXmlContent (node link: http://127.0.0.1:63320/node?ref=r%3A67fd3fc1-34e7-4a5b-bf5a-87941fd4bee4%28com.mbeddr.mpsutil.xmlImport.plugin%29%2F2391690587316423693). You can also reach it by pressing Ctrl+N+N and then type “pasteAsXmlContent” and it will be the first item that MPS finds.
If you don’t have the mbeddr platform installed and don’t want to, you can at least get an idea of the mechanism on how to build an importer that can just import by copy-paste by looking at the built-in MPS java importer. Just check out the pasteAsJavaClass action: Ctrl+N+N and type “PasteAsJavaClass”. Alternatively, you can find that in the modules pool under solutions/jetbrains/mps/java/platform/actions/Actions/PasteAsJavaClass.
By the way: for generating XML from a model (as opposed to just dumping the raw model as XML, as my post describes), you could also have a look at the jetbrains.mps.core.xml language. If you import this language in your generator, you can generate something more close to XML.
I hope this information helps you in some way.