Thoughts Electrique

Manipulating OpenCms XMLContent programatically (some examples)

Because someone asked on the mailing list and I keep forgetting the respective API calls to manipulate an OpenCms XMLContent programatically.

This is just a raw code dump not a step by step tutorial.

You can also download a ZIP file for importing it into OpenCms. But you have to adjust the paths manually.

Example JSP calls

<%@ page import="org.opencms.file.*,
                 org.opencms.jsp.*,
                 org.opencms.xml.*,
                 org.opencms.xml.content.*,
                 org.opencms.xml.types.*,
                 org.opencms.util.*,
                 java.util.*" %><%

// The resource to read
String resource = "/system/modules/de.himberger.sebastian.site/schemas/publication/manipulate.html";

// The locale to use
Locale locale = new Locale("en");

// The names of the elements
String versionElement = "Version";
String fileElement = "File";

CmsJspActionElement cmsa = new CmsJspActionElement(pageContext,request,response);
CmsObject cmso = cmsa.getCmsObject();

// read the resource
CmsResource xmlContentResource = cmso.readResource(resource);
CmsFile xmlContentFile = CmsFile.upgrade(xmlContentResource,cmso);

// Output current xml
out.println("<h1>Before</h1>");
out.println("<pre>" + CmsStringUtil.escapeHtml((new String(xmlContentFile.getContents()))) + "</pre>");

// build up the xml content instance
CmsXmlContent xmlContent = CmsXmlContentFactory.unmarshal(cmso,xmlContentFile);

// This is a new version (in this case it is a nested schema
I_CmsXmlContentValue addedVersionValue = xmlContent.addValue(cmso,versionElement ,locale,0);

// Add a new element to the created version (nested schema)
I_CmsXmlContentValue addedFileValueRaw = xmlContent.addValue(
  cmso,addedVersionValue.getPath() + "/" + fileElement,locale,0);
CmsXmlVfsFileValue addedFileValue = (CmsXmlVfsFileValue ) addedFileValueRaw;
addedFileValue.setStringValue(cmso,resource);

// manipulate an element
I_CmsXmlContentValue theSameValueWeAdded = xmlContent.getValue(
  addedVersionValue.getPath() + "/" + fileElement,locale);
// ... do the same as above

// add and remove a value
I_CmsXmlContentValue secondAddedVersionValue = xmlContent.addValue(cmso,
  versionElement,locale,addedVersionValue.getIndex()+1);

out.println("<h1>After adding</h1>");
out.println("<pre>" + CmsStringUtil.escapeHtml((new String(xmlContent.marshal()))) + "</pre>");

xmlContent.removeValue(secondAddedVersionValue.getPath(),locale,0);

out.println("<h1>After removing</h1>");
out.println("<pre>" + CmsStringUtil.escapeHtml((new String(xmlContent.marshal()))) + "</pre>");

// In the real world you would now do
// xmlContentFile.setContents(xmlContent.marshal());
// cmso.writeResource(xmlContentFile);
%>

Version schema

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

       <xsd:include schemaLocation="opencms://opencms-xmlcontent.xsd"/>
       <xsd:element name="XmlContentPublicationVersions"
                    type="OpenCmsXmlContentPublicationVersions"/>

       <xsd:complexType name="OpenCmsXmlContentPublicationVersions">
               <xsd:sequence>
                       <xsd:element name="XmlContentPublicationVersion"
                                    type="OpenCmsXmlContentPublicationVersion"
                                    minOccurs="0" maxOccurs="unbounded"/>
               </xsd:sequence>
       </xsd:complexType>

       <xsd:complexType name="OpenCmsXmlContentPublicationVersion">
              <xsd:sequence>
                      <xsd:element name="Title" type="OpenCmsString" />
		      <xsd:element name="PublicationDate" type="OpenCmsDateTime" />
                      <xsd:element name="Description" type="OpenCmsString" />
                      <xsd:element name="File" type="OpenCmsVfsFile" minOccurs="0"
                                   maxOccurs="10" />
              </xsd:sequence>
              <xsd:attribute name="language" type="OpenCmsLocale" use="optional"/>
       </xsd:complexType>

</xsd:schema>

Publication schema

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified">

       <xsd:include schemaLocation="opencms://opencms-xmlcontent.xsd"/>
       <xsd:include
            schemaLocation="opencms://system/modules/de.himberger.sebastian.site/schemas/publication/publication-version.xsd"/>

       <xsd:element name="XmlContentPublications" type="OpenCmsXmlContentPublications"/>

       <xsd:complexType name="OpenCmsXmlContentPublications">
               <xsd:sequence>
                       <xsd:element name="XmlContentPublication"
                                    type="OpenCmsXmlContentPublication"
                                    minOccurs="0" maxOccurs="unbounded"/>
               </xsd:sequence>
       </xsd:complexType>

       <xsd:complexType name="OpenCmsXmlContentPublication">
              <xsd:sequence>
                      <xsd:element name="Title" type="OpenCmsString" />
                      <xsd:element name="Subtitle" type="OpenCmsString" />
                      <xsd:element name="Description" type="OpenCmsHtml" />
                      <xsd:element name="Version"
                                   type="OpenCmsXmlContentPublicationVersion"
                                   minOccurs="0" maxOccurs="unbounded" />
              </xsd:sequence>
              <xsd:attribute name="language" type="OpenCmsLocale" use="required"/>
       </xsd:complexType>

</xsd:schema>

Tags: , , , ,

3 Responses to “Manipulating OpenCms XMLContent programatically (some examples)”

  1. Mike Says:

    Hey Sebastian,

    Just a heads-up – looks like you posted the version schema twice above. I took a look at the zip file to see the publication schema, but it might help someone else if you updated the posted schema.

    Thanks for the example, it helped me loads. If you are willing and able, would be nice also to see an example using CmsXmlNestedContentDefinition.

  2. Sebastian Says:

    Hi Mike,

    great! Thanks very much for the hint. The next two days I’m swamped with work but I’ll look into it and will also post a CmsXmlNestedContentDefinition example on the weekend.

    Best regards,
    Sebastian

  3. Mike Says:

    Thanks Sebastian :)

Leave a Reply