Although there are a lot of evaluators available in Mule CE it is very easy to add your own evaluator. In my case we have a self defined message format that holds some properties in the header of a message (similar to JMS Message, MuleMessage, etc.). To get access to these properties in the Mule config I created a custom evaluator that made this possible. Although there will be other solutions available for this situation, I found this a nice (pragmatic) way to solve it. It also provides a base to start from in case of possible changes in the future.
The XML schema that describes our message looks like:

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xs:schema xmlns:tns="http://www.redstream.nl/message/v01_0"
  3.            xmlns:xs="http://www.w3.org/2001/XMLSchema"
  4.            targetNamespace="http://www.redstream.nl/message/v01_0"
  5.            elementFormDefault="qualified">
  6.     <xs:element name="message" type="tns:MessageType"/>
  7.     <xs:complexType name="MessageHeaderType">
  8.         <xs:annotation>
  9.             <xs:documentation>The header for a message. Contains all metadata about the message.</xs:documentation>
  10.         </xs:annotation>
  11.         <xs:sequence>
  12.             <xs:element name="messageVersion" type="tns:versionNumberType" minOccurs="1" maxOccurs="1"/>
  13.             <xs:element name="PropertySet" type="tns:PropertySetType" minOccurs="0" maxOccurs="1"/>
  14.         </xs:sequence>
  15.     </xs:complexType>
  16.     <xs:complexType name="MessageType">
  17.         <xs:sequence>
  18.             <xs:element name="MessageHeader" type="tns:MessageHeaderType" minOccurs="1" maxOccurs="1"/>
  19.             <xs:element name="MessageBody" type="tns:MessageBodyType" minOccurs="0" maxOccurs="1"/>
  20.         </xs:sequence>
  21.     </xs:complexType>
  22.     <xs:complexType name="MessageBodyType">
  23.         <xs:sequence>
  24.             <xs:any minOccurs="0" maxOccurs="1"/>
  25.         </xs:sequence>
  26.     </xs:complexType>
  27.     <xs:complexType name="PropertyType">
  28.         <xs:attribute name="key" type="xs:string" use="required"/>
  29.         <xs:attribute name="value" type="xs:string"/>
  30.     </xs:complexType>
  31.     <xs:complexType name="PropertySetType">
  32.         <xs:annotation>
  33.             <xs:documentation>Set of properties</xs:documentation>
  34.         </xs:annotation>
  35.         <xs:sequence>
  36.             <xs:element name="Property" type="tns:PropertyType" minOccurs="0" maxOccurs="unbounded"/>
  37.         </xs:sequence>
  38.     </xs:complexType>
  39.     <xs:simpleType name="versionNumberType">
  40.         <xs:annotation>
  41.             <xs:documentation>Type used to define a Message versionNumber</xs:documentation>
  42.         </xs:annotation>
  43.         <xs:restriction base="xs:string">
  44.             <xs:pattern value="v[0-9]{2}_[0-9]{1}"/>
  45.             <xs:length value="5"/>
  46.         </xs:restriction>
  47.     </xs:simpleType>
  48. </xs:schema>

And example message looks like this:

XML:
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <tns:message xsi:schemaLocation="http://www.redstream.nl/message/v01_0 message_v01_0.xsd" xmlns:tns="http://www.redstream.nl/message/v01_0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  3.     <tns:MessageHeader>
  4.         <tns:messageVersion>v01_0</tns:messageVersion>
  5.         <tns:PropertySet>
  6.             <tns:Property key="SOURCE_SYSTEM" value="CRM" />
  7.             <tns:Property key="ENTITY" value="Order" />
  8.             <tns:Property key="VERSION" value="v01_0" />
  9.         </tns:PropertySet>
  10.     </tns:MessageHeader>
  11.     <tns:MessageBody>
  12.             <payload-root>Blablabla</payload-root>
  13.         </tns:MessageBody>
  14. </tns:message>

To get access to the 'Property' elements in the message-header via an 'evaluator expression' I created the following Java class based on the info given here:

JAVA:
  1. package nl.redstream.evaluator;
  2.  
  3. import nl.redstream.cdm.util.JaxbUtil;
  4. import java.util.List;
  5. import javax.xml.bind.JAXBException;
  6. import nl.redstream.message.v01_0.Message;
  7. import nl.redstream.message.v01_0.PropertySetType;
  8. import nl.redstream.message.v01_0.PropertyType;
  9. import org.apache.log4j.Logger;
  10. import org.mule.api.MuleMessage;
  11. import org.mule.api.expression.ExpressionEvaluator;
  12. import org.mule.api.expression.RequiredValueException;
  13. import org.mule.config.i18n.CoreMessages;
  14.  
  15. /**
  16. *
  17. * @author pascal
  18. */
  19. public class CdmMessageEvaluator implements ExpressionEvaluator {
  20.  
  21.     public static final String NAME = "cdm-msg-property";
  22.    
  23.     protected static Logger logger = Logger.getLogger(CdmMessageEvaluator.class);
  24.  
  25.     public Object evaluate(String expression, MuleMessage msg) {
  26.         Object result = null;
  27.  
  28.         boolean required;
  29.  
  30.         //Is the header optional? the '*' denotes optional
  31.         if (expression.endsWith("*")) {
  32.             expression = expression.substring(expression.length() - 1);
  33.             required = false;
  34.         } else {
  35.             required = true;
  36.         }
  37.  
  38.         Message cdmMsg = null;
  39.         //Look up the property on the message
  40.         if (msg.getPayload() instanceof Message)
  41.         {
  42.             cdmMsg = (Message) msg.getPayload();
  43.         } else if (msg.getPayload() instanceof String)
  44.         {
  45.             try {
  46.                 // Apparantly we are getting the message as an XML String
  47.                 // So use jaxb to create a Object of it
  48.                 cdmMsg =
  49.                         JaxbUtil.unmarshal(Message.class,
  50.                         msg.getPayload().toString());
  51.             } catch (JAXBException ex) {
  52.                 throw new UnsupportedOperationException("Unexpected String input received (not a Ship Message)");
  53.             }
  54.  
  55.         } else {
  56.             // It's not an expected payload. Fail this operation.
  57.              throw new UnsupportedOperationException("Unexpected inputtype received: " + msg.getPayload().getClass().getName());
  58.         }
  59.  
  60.         result = getProperty(cdmMsg.getMessageHeader().getPropertySet(),expression.toUpperCase());
  61.  
  62.         if (result == null && required) {
  63.             throw new RequiredValueException(CoreMessages.expressionEvaluatorReturnedNull(NAME, expression));
  64.         }
  65.         return result;
  66.     }
  67.  
  68.     public String getName() {
  69.         return NAME;
  70.     }
  71.  
  72.     public void setName(String name) {
  73.         throw new UnsupportedOperationException("setName");
  74.     }
  75.  
  76.     private String getProperty(PropertySetType propertySet, String property)
  77.     {
  78.         List<PropertyType> props = propertySet.getProperties();
  79.  
  80.         String value = null;
  81.         for (PropertyType prop: props) {
  82.              if (prop.getKey().toUpperCase().equals(property))
  83.              {
  84.                  value = prop.getValue();
  85.                  break;
  86.              }
  87.         }
  88.         return value;
  89.     }
  90. }

I think the code is fairly straightforward. In the method 'evaluate' I receive the payload of the MuleMessage and I check to see if the payload is a JAXBObject of the type Message. If it is a String I assume I receive the XML message as payload and transform the String to the expected JAXB object myself (see this post for more details about this subject).
When I have access to the JAXBObject I simply question the properties of the message for the property name that is supplied with the expression. If a value is found this is returned by the expression.
To make use of this evaluator I 'bootstrapped' it with the Mule application. This can simply be done by adding the file 'registry-bootstrap.properties' to your classpath in the folder 'META-INF/services/org/mule/config' (as explained here). In this file I put:

CODE:
  1. object.1=nl.redstream.evaluator.CdmMessageEvaluator

And that's it. To make use of this evaluator I have in my Mule config:

XML:
  1. <expression-recipient-list-router evaluator="custom" custom-evaluator="cdm-msg-property" expression="ADDR_LIST" transformer-refs="JaxbObjectToCdmXml">

This will take the property 'ADDR_LIST' out of my Message and use it as outbound Endpoint, but I will explain that in another post.