Enhanced XML Import
Introduction
Goal
Use Hippo-specific enhancements to JCR System View XML to implement advanced import or bootstrap requirements.
Background
With Hippo Repository you can import content using an enhanced form of the JCR-specified System View XML. System View XML is an XML-serialized form of JCR content and is defined by the JCR specification. With the help of System View XML it is possible to serialize and deserialize any JCR content whatsoever. Hippo Repository adds semantics for additional requirements such as merging new content with existing content during deserialization and importing content from external files.
Example
The following is an example of an enhanced System View XML file, below are the possible directives you can specify.
<?xml version="1.0" encoding="UTF-8"?> <sv:node xmlns:sv="http://www.jcp.org/jcr/sv/1.0" xmlns:esv="http://www.onehippo.org/jcr/xmlimport" sv:name="foo" esv:merge="combine"> <sv:node sv:name="bar" esv:merge="combine"> <sv:property sv:name="property1" sv:type="String"> <sv:value>value1</sv:value> </sv:property> <sv:property sv:name="property2" sv:type="String" esv:merge="append"> <sv:value>value_x</sv:value> <sv:value>value_y</sv:value> </sv:property> <sv:node sv:name="baz" esv:merge="insert" esv:location="qux"> <sv:property sv:name="jcr:primaryType" sv:type="Name"> <sv:value>myns:mytype</sv:value> </sv:property> <sv:property sv:name="myns:myproperty" sv:type="String"> <sv:value esv:file="/path/to/file.txt" /> </sv:property> </sv:node> </sv:node> </sv:node>
Directives
xmlimport namespace
Start by adding the enhancement namespace to the first sv:node.
The top-level <sv:node> should always have the attribute xmlns:sv="http://www.jcp.org/jcr/sv/1.0". To use the enhanced XML add another XML namespace xmlns:esv="http://www.onehippo.org/jcr/xmlimport" . This namespace allows you to add the attributes esv:merge and esv:location to sv:node elements.
Merging nodes
When a node already exists and you want to add (multiple) properties and/or child nodes to the node while preserving the existing node, add the attribute esv:merge="combine" to the corresponding sv:node. This instructs the deserializer to treat the existing node with that name as a merge target. The existing node is used as a base, and all properties and child nodes of the imported XML node are added. Note that if these imported child nodes also have the combine directive, merging those nodes with an existing node will also be attempted. Changing the primary type using the combine directive is not possible, and if the node does not already exist, a normal import will take place. A regular node import requires the property jcr:primaryType to be present in the import, but when combining nodes, you can omit the jcr:primaryType property (as well as the jcr:mixinTypes).
Change primary node type or mixins
When you want to change the primary node type or mixins of an existing node you must use the esv:merge="overlay" directive. It works similar to the combine directive with the addition of being able to change the primary and mixin types.
Inserting nodes in a specific location
Both when combining nodes, and during a regular XML import, a newly created node is always the last child node of the parent node. With the directive esv:merge="insert" you can insert a node at a specific location between existing sibling nodes if the parent is an orderable node. The additional attribute esv:location will instruct before which other node the node needs to be inserted. In case of same-name siblings, you can append the node name with an index between brackets.
Skip import when node already exist
You can also skip a node and all content below it when it already exists by specifying the directive esv:merge="skip" .
Appending values to a multi-value property
To append values to a multi-value property you can specify the directive esv:merge="append".
Overriding properties
When a node in an XML file is combined or overlayed with another node, the XML file would normally only contain the properties that need to be added to the original node. However, if a property already exists, the imported property will overwrite the existing property when you do not specify any esv:merge directive on the property. But this will cause a warning that the property already existed. When you expect to override a property it is cleaner to specify a esv:merge="override" on the property to be overridden.
Importing a property value from an external file
String and binary property values can be imported from an external file by adding the attribute esv:file to the property's sv:value element, specifying a path relative to the containing jar file's root (leading slash optional).
Additional Features
Set a Reference Property
A Reference property is used to provide a named reference to a node elsewhere in the content repository. The value of the property is the UUID of the node to which it refers.
To avoid hard-coding such a UUID in the XML, use a String property with ___pathreference appended to its name. The value of the property should be the absolute JCR path to the node to which the property refers:
<sv:property sv:name="hippo:related___pathreference" sv:type="String"> <sv:value>/content/documents/myhippoproject/events/2016/07/workshop</sv:value> </sv:property>
On import, Hippo Repository will resolve the path reference and store it as a proper Reference property. To make sure that the path reference is resolved, the referenced node must be imported before the reference.