XML validation using CAMV framework Tutorial

XML validation usually can be done in Schema level, but sometimes it is not feasible to validate xml in schema level, it is too strict, and real world application especially the large scale one, can’t enforce schema level validation due to various of reasons.

what is CAM editor and CAMV framework ?
from wiki
CAM editor is an open source tool for XML exchange structure development built using the open public OASIS CAM standard.
CAM editor provides full life-cycle management of XML Schema and supports the use of Canonical Model dictionary components.
Starting with CAM editor v2.3 release, support was added for SQL data to XML open data generation (Open-XDX) using code-free dynamic methods and a simple drag and drop visual metaphor. See these video tutorial materials introducing the Open-XDX approach.
CAM editor is compatible with the NIEM approach for information exchange integration.
The XML schema output from CAM editor is suitable for use in middleware messaging or other enterprise integration patterns that require model compliant XML schema.
In addition, CAM editor provides support for solving integration challenges found in enterprise integration. It works with industry standard frameworks (List of XML schemas and generation of model/framework compliant XML schema along with enabling core component message assembly (CCMA).
Also designed for integration with Service-oriented architecture, CAM editor supports use with other message-based integration patterns such as Enterprise Application Integration (EAI) and ebXML.

CAM editor can be download here, http://sourceforge.net/projects/camprocessor/files/
it is a eclipse based IDE

First, we create the validation rule template file, this can be done easily with provided IDE, which can be downloaded here.
Suppose we have such schema

<?xml version="1.0" encoding="ISO-8859-1" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">

<xs:element name="shiporder">
  <xs:complexType>
    <xs:sequence>
      <xs:element name="orderperson" type="xs:string"/>
      <xs:element name="shipto">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="name" type="xs:string"/>
            <xs:element name="address" type="xs:string"/>
            <xs:element name="city" type="xs:string"/>
            <xs:element name="country" type="xs:string"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
      <xs:element name="item" maxOccurs="unbounded">
        <xs:complexType>
          <xs:sequence>
            <xs:element name="title" type="xs:string"/>
            <xs:element name="note" type="xs:string" minOccurs="0"/>
            <xs:element name="quantity" type="xs:positiveInteger"/>
            <xs:element name="price" type="xs:decimal"/>
          </xs:sequence>
        </xs:complexType>
      </xs:element>
    </xs:sequence>
    <xs:attribute name="orderid" type="xs:string" use="required"/>
  </xs:complexType>
</xs:element>

</xs:schema> 

to get our validation rules template up and running very quickly, we took the shortcut to start from schema, then we tweak the rules.

CAMVEDitor

Ok Save the template.

CAMVEDitor

the xml file to be validated.

<?xml version="1.0" encoding="ISO-8859-1"?>

<shiporder orderid="889923"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="schema.xsd">
  <orderperson>John Smith</orderperson>
  <shipto>
    <name>Ola Nordmann</name>
    <address>Langgt 23</address>
    <city>4000 Stavanger</city>
    <country>Norway</country>
  </shipto>
  <item>
    <title>Empire Burlesque</title>
    <note>Special Edition</note>
    <quantity>1</quantity>
    <price>10.90</price>
  </item>
  <item>
    <title>Hide your heart</title>
    <quantity>1</quantity>
    <price>9.90</price>
  </item>
</shiporder> 

To test it, we can use IDE’s XML-> Open XML, then Run -> Run Template to run it.

CAMVEDitor

The bottom part is the validation result.

Ok, done, that is simply the schema validation.

Now, we can start tweak our rules to make it more looser or tighter.

we can add a new rules
cam editor

There are many prebuilt validation functions
cam editor

Lets restrict the name as only allow Sam and Jack, then run the validation again. now we get an expected validation error.

Scam editor

To integrate it into our application, we need to compile the template first.

cam editor

The rule file we edited is like bears such format, basically we can simply treat it as 2 parts,
1. the as:AssemblyStructure parts, which tells the engine how the xml is be structured
2. rule parts, those rules usually usually consist of following parts, pre-defined function, and usually it take an xpath as parameter to indicate where should this rules apply to, this can be absolute path or a relative path.
and also, it provides context condition, means only context=true then the function will be executed.
note: play with the IDE to set the rules, and then have a check how those rules will finally be in the format of xml.

<as:CAM
 xmlns:as="http://www.oasis-open.org/committees/cam"
 xmlns:camed="http://jcam.org.uk/editor"
 xmlns:xml="http://www.w3.org/XML/1998/namespace"
 xmlns:xsd="http://www.w3.org/2001/XMLSchema" CAMlevel="1" version="1.0">
  <as:Header>
    <as:Description>Generated for shiporder  by XSD 2 CAM generator v2.12</as:Description>
    <as:Owner>To be Completed</as:Owner>
    <as:Version>0.1</as:Version>
    <as:DateTime>2013-06-27T21:42:43</as:DateTime>
  </as:Header>
  <as:AssemblyStructure>
    <as:Structure taxonomy="XML" ID="shiporder" reference="">
      <shiporder orderid="%string%">
        <orderperson>%string%</orderperson>
        <shipto>
          <name>%string%</name>
          <address>%string%</address>
          <city>%string%</city>
          <country>%string%</country>
        </shipto>
        <item>
          <title>%string%</title>
          <note>%string%</note>
          <quantity>%1%</quantity>
          <price>%54321.00%</price>
        </item>
      </shiporder>
    </as:Structure>
  </as:AssemblyStructure>
  <as:BusinessUseContext>
    <as:Rules>
      <as:default>
        <as:context>
          <as:constraint action="makeOptional(//item/note)" />
          <as:constraint action="setNumberMask(//item/price,######.##)" />
          <as:constraint action="setNumberMask(//item/quantity,######)" />
          <as:constraint action="makeRepeatable(//shiporder/item)" />
          <as:constraint action="restrictValues(//shipto/name,'Sam'|'Jack')">
            <as:annotation>
              <as:documentation type="documentation">Only Sam and Jack as name are allowed</as:documentation>
            </as:annotation>
          </as:constraint>
        </as:context>
      </as:default>
    </as:Rules>
  </as:BusinessUseContext>
  <as:Extension name="uk.org.jcam.camed.extensions.StructureAnnotations">
    <camed:annotation item="//shiporder">
      <camed:documentation type="Generated">Built by XSD 2 CAM - 2.12 - 2013-06-27T21:42:43.532+10:00</camed:documentation>
    </camed:annotation>
  </as:Extension>
</as:CAM>

Compile and Save as .cxx format, then we can use it in our application
Library can be donwload from here

http://sourceforge.net/projects/camprocessor/files/CAM%20Validator/Releases/

java Integration

 
package com.zenmeo.validation.validator;

import java.io.FileNotFoundException;
import java.io.StringReader;
import java.util.List;

import org.w3c.dom.Document;
 
import com.zenmeo.validation.ws.types.ValidationErrorType;
import com.zenmeo.validation.ws.types.ValidationResponseType;

import net.sf.saxon.s9api.SaxonApiException;

 
import uk.org.jcam.camv.errorhandling.CAMVMessage;
import uk.org.jcam.camv.errorhandling.ElementErrorHandler;
import uk.org.jcam.camv.validator.TemplateValidator;
import uk.org.jcam.sdom.AttributeException;
import uk.org.jcam.sdom.DocumentException;
import uk.org.jcam.sdom.ElementException;

public class CAMValidator  {
	public static void main(String[] args) throws DocumentException,
			FileNotFoundException, ElementException, AttributeException,
			SaxonApiException {
		
		String templateDocument = "C:/XSD.cxx";
	    String xmlInput= "C:/PRD_FAIL.XML";

	    CAMValidator validator=new CAMValidator(templateDocument);
	    
	    
	    validator.validate(xmlInput);

	    for(CAMVMessage camMsg:validator.getErrors()){
			ValidationErrorType type=new ValidationErrorType();
		 	type.setErrorLocation(camMsg.getItempath());
			type.setErrorMessage(camMsg.getMessage());
			System.out.println(camMsg.getItempath());
			System.out.println(camMsg.getMessage());
		} 
	}
 	
    private TemplateValidator tv;

	public CAMValidator(String configuraionLocation) {
		try {
			tv=new TemplateValidator(configuraionLocation);
			tv.setErrHandler(new ElementErrorHandler());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
	}
	public boolean validate(Object xmlSource){
		if(tv==null){
			//if validation template loading failed, we skip it, so that it won't impact the whole work flow
			return true;
		}
		boolean tvResult=true;
		try {
			tvResult = tv.validate(xmlSource);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			return true;
		}
		return tvResult;
	}

	 
	
	public ValidationResponseType getAllErrorsInXMLResoponse(){
		ValidationResponseType result=new ValidationResponseType();
		for(CAMVMessage camMsg:this.getErrors()){
			ValidationErrorType type=new ValidationErrorType();
		 	type.setErrorLocation(camMsg.getItempath());
			type.setErrorMessage(camMsg.getMessage());
		 	result.getValidationErrorType().add(type);
		}
		return result;
	}
	public List<CAMVMessage> getErrors(){
		return tv.getErrorHandler().getErrors();
	} 
}

Leave a Comment