.. ******************************************************************************* * MetaFactory.io R2 * Technical Documentation * * File name : CIX_JCIE_XML-Files.rst * Created by : Marnix Bochove (original text) * Last update : 22-03-2021 * Updated by : Niels de Nies * * MetaFactory BV Amsterdam ******************************************************************************* .. include:: /external-links.txt .. include:: /inline-images.txt .. include:: /metadata_include.txt XML files ========= MetaFactory produces several kinds of files: - java source code, - xml files and - plain text files like JavaScript, HTML, JSON, YAML. The element is the way to create XML files such as Maven’s pom.xml. .. rubric:: Usage .. code-block:: xml :caption: Syntax :name: XML files-01 :linenos: :emphasize-lines: 4 ... ...any valid xml allowed here ... The element is the root element of the created xml document. Everything is copied into this root element except some predefined attributes. Namespaces that you define in children of the element (e.g. the Maven namespace for pom.xml) are copied to its generated XML output. However, the MetaFactory namespaces that belong to the pattern are removed from the result. .. rubric:: Attributes .. list-table:: **attributes of ** :widths: 20 80 :header-rows: 1 :class: tight-table * - Name - Details * - __filename - Used to set the name of the created xml file. Mandatory * - __path - Path where the xml file is saved. * - __root - Used to set root of a DOCTYPE. Suppose this DOCTYPE must be declared for a xml file: .. code-block:: xml These attributes of the element need to be set: .. code-block:: :name: XML files-02 :linenos: :emphasize-lines: 3-5 ... * - __publicid - Used to set the publicid part of a DTD reference. Used to set a DOCTYPE * - __systemid - Used to set the systemid part of a DTD reference. Used to set a DOCTYPE * - __baseuri - Set the xml:base_ attribute of the xml document. * - __foreach - Indicates if XML File must be created foreach element in model (value of foreach determines what model element). Possible values: package, object, attribute, reference, object.attribute, object.reference * - __condition - An expression that evaluates to true or false. Generation of the current file wil precede if true and otherwise not. Example: .. code-block:: xml __condition="${object.name}=Person" In this case, the package is generated only if the current model object has the name: Person. This works only if all model objects are iterated (foreach=”object”). * - __package - The name of the package in the model (model.xml) that must be used to apply the foreach attribute. * - __var0 .. __var20 - Value that you wish to store in the pre-defined variable with the name var0 (up to var20). Reference to this value can be made later by means of: ${var0} (up to var20). This can be used in both the code_instruction and in a snippet (freemarker or velocity template). .. rubric:: Sub elements .. list-table:: **sub elements of ** :widths: 15 70 15 :header-rows: 1 :class: tight-table * - Name - Details - Number * - body - Used as root element of the XML file to create, so only 1 child is allowed. Below this child element every well formed xml is allowed. If iteration is required all child elements can also use these reserved attributes: .. code-block:: __foreach, __condition, __package and __var0 till __var5 - 0 or 1 .. rubric:: Namespace The entire code_instruction has to be in the code_instruction namespace, whereas the xml file to be created does not. The code_instruction namespace is therefore removed from the result. Occasionally no namespace is given for the document to be created, however it does contain elements that also occur in the code_instruction namespace. If, according to the code_instruction, an element is not valid, the xml parser gives an error message. To prevent the parser treating the element as part of the code_instruction namespace, we can use the namespace reserved with xml: as the prefix. Elements with this prefix are created, without this prefix, in the resulting xml document. This xml prefix indicates that the element doesn’t belong to the code_instruction namespace. |Eye S| A better way to deal with this problem is defining the code_instruction namespace with a prefix (instead of default namespace). An example of a situation where this is necessary occurs when creating hibernate xml mapping files for linking classes to database tables. In this mapping document use is made of a class element: .. code-block:: xml :caption: Syntax :linenos: :emphasize-lines: 10,15 .... .. rubric:: Snippets producing xml Sometimes it is useful for the whole document (or a part) to be created by means of a “snippet”, in order to benefit from the power of velocity or freemarker. To utilise a snippet when creating the document and still maintain well-formed xml, you can use the the reserved element '': .. code-block:: xml ${snippet.xml.path.to.file.templatename} The advantage is that the snippet itself does not have to make a 1-root element xml. All xml elements created are added as children of the parent of the special **** element. **Example** In the following example, the .page.xml document is created of a JBoss Seam web application. In this document, several param elements occur each of which is a child of the root element page. Some param elements appear to have a rather more complex structure, making it impossible (or difficult) to describe these with _foreach. Use should therefore be made of a velocity snippet (or freemarker). |Eye S| This example is a little bit outdated. The required xml in the pattern appears as follows: .. code-block:: xml :caption: Example :linenos: :emphasize-lines: 37 ${snippet.seam.page.edit.hasPermission} #{messages['edit.text']} #{messages['${firstLower(${object.name})}.text']} (#{${firstLower(${object.name})}Home.${firstLower(${object.name})}Id}) ${snippet.seam.page.edit.referencennParams} Contents of the velocity template: .. code-block:: ##stop if $currentModelObject is null #if(!$currentModelObject) $generator.error("currentModelObject not found in context") #end #set($modelobject=$currentModelObject) ## element of model #set($modelObjectName=$currentModelObject.getAttributeValue("name")) #set($modelObjectNameFL=${generator.firstLower($modelObjectName)}) #set($nnReferenceProperties=$generator.getPropertyElements($modelobject,"reference.nn")) #foreach($nnReferenceProperty in $nnReferenceProperties) #set($nnReferencePath=$nnReferenceProperty.getTextNormalize()) ##// handle nn reference: $nnReferencePath #set($tokens=$nnReferencePath.split('\.')) #set($tokenList=$generator.asList($tokens)) #set($startObject=$tokenList.get(0)) ##find the modelObject with name $startObject => this is just a check, because we only need the name of the object which we already know #set($modelPackage=$context.getModelPackage("domain_model")) #set($nnReferenceObjectElement=$generator.findChildByAttribute($modelPackage, "object", "name", "$startObject")) #set($nnReferenceObjectName=$nnReferenceObjectElement.getAttributeValue("name")) #set($nnReferenceObjectNameFL=${generator.firstLower($nnReferenceObjectName)}) #end