FormalExpressions CDATA

Hi there,

I’ve extended bpmn-js for activiti requisites and at the moment im having trouble importing XML files that cointain CDATA like xml below:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:activiti="http://activiti.org/bpmn" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:process id="Process_1" name="Process_1" isExecutable="true">
    <bpmn2:startEvent id="StartEvent_1">
      <bpmn2:outgoing>SequenceFlow_0172kww</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:exclusiveGateway id="ExclusiveGateway_0iy4x4i">
      <bpmn2:incoming>SequenceFlow_0172kww</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_1jkcy1g</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:sequenceFlow id="SequenceFlow_0172kww" sourceRef="StartEvent_1" targetRef="ExclusiveGateway_0iy4x4i" />
    <bpmn2:task id="Task_0ntkrd9" activiti:async="true">
      <bpmn2:incoming>SequenceFlow_1jkcy1g</bpmn2:incoming>
    </bpmn2:task>
    <bpmn2:sequenceFlow id="SequenceFlow_1jkcy1g" sourceRef="ExclusiveGateway_0iy4x4i" targetRef="Task_0ntkrd9">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">&lt;![CDATA[${m = 0 &amp;&amp; y = 1}]]&gt;</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="Process_1">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="418" y="240" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ExclusiveGateway_0iy4x4i_di" bpmnElement="ExclusiveGateway_0iy4x4i" isMarkerVisible="true">
        <dc:Bounds x="504" y="233" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_0172kww_di" bpmnElement="SequenceFlow_0172kww">
        <di:waypoint x="454" y="258" />
        <di:waypoint x="504" y="258" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="Task_0ntkrd9_di" bpmnElement="Task_0ntkrd9">
        <dc:Bounds x="604" y="218" width="100" height="80" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_1jkcy1g_di" bpmnElement="SequenceFlow_1jkcy1g">
        <di:waypoint x="554" y="258" />
        <di:waypoint x="604" y="258" />
      </bpmndi:BPMNEdge>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

Bpmn-js doesn’t remove the CDATA part if it doesn’t contain “&&”, for example <![CDATA[${a==2}]]> or <![CDATA[${a==2 || b == 3}]]> isn’t removed, but <![CDATA[${a==2 **&&** b==3}]]>, the CDATA part is removed (and && is parsed to &amp&amp but that is ok, for now).

I’ve read somewhere that if this happens in the export phase, it is a feature and not a bug - but it isn’t, at the moment (After my modifications) the download keeps the CDATA, the problem is when i import a XML is removes.

Any idea to prevent this? I need it to not be removed to prevent errors when reading XML file in activiti (because “&” is a special character).

Please share a running / prototypical example that clearly shows what you’re trying to achieve, what is working and what is not.

Use our existing starter projects to quickly hack it or share your existing, partial solution on GitHub. Provide the necessary pointers that allow us to quickly understand where you got stuck.

This way we may be able to help you in a constructive manner.

Thanks :heart:

I’ll try to build a prototypical example asap, thanks.

To be honest I don’t quite understand the problem yet.

The diagram does not contain an actual CDATA section, it is escaped instead:

    <bpmn2:sequenceFlow id="SequenceFlow_1jkcy1g" sourceRef="ExclusiveGateway_0iy4x4i" targetRef="Task_0ntkrd9">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">&lt;![CDATA[${m = 0 &amp;&amp; y = 1}]]&gt;</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>

As a result our toolkit will read the thing as an actual raw string:

sequenceFlow.conditionExpression; // "<![CDATA[${m = 0 && y = 1}]]>"

This is the intended behavior or am I missing anything here?

It is the intended behavior, yes, i’m still solving other issues.

The problem is it is deleting the CDATA part from the string when im editing an existing diagram (either by drag&drop or by importing from server). I’m still going to debug it and see if it was something i had changed.

1 Like

Well no need to debug if i did something wrong… I just tested in the example bpmn-js-examples-master\properties-panel-extension, imported this xml:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:activiti="http://activiti.org/bpmn" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:process id="TesteAnd" name="TesteAnd" isExecutable="true">
    <bpmn2:startEvent id="StartEvent_1">
      <bpmn2:outgoing>SequenceFlow_1nevhlf</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:exclusiveGateway id="ExclusiveGateway_1u8iq8b" default="SequenceFlow_0fage2o">
      <bpmn2:incoming>SequenceFlow_1nevhlf</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_040s2zr</bpmn2:outgoing>
      <bpmn2:outgoing>SequenceFlow_0fage2o</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:sequenceFlow id="SequenceFlow_1nevhlf" sourceRef="StartEvent_1" targetRef="ExclusiveGateway_1u8iq8b" />
    <bpmn2:endEvent id="EndEvent_0fkrjbp">
      <bpmn2:incoming>SequenceFlow_040s2zr</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_040s2zr" sourceRef="ExclusiveGateway_1u8iq8b" targetRef="EndEvent_0fkrjbp">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression"><![CDATA[${a == 2 && b == 3}]]></bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="SequenceFlow_0fage2o" sourceRef="ExclusiveGateway_1u8iq8b" targetRef="Task_04n6q8e" />
    <bpmn2:endEvent id="EndEvent_1v1zpde">
      <bpmn2:incoming>SequenceFlow_0yvfjuh</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_0yvfjuh" sourceRef="Task_04n6q8e" targetRef="EndEvent_1v1zpde" />
    <bpmn2:userTask id="Task_04n6q8e" activiti:async="true">
      <bpmn2:extensionElements>
        <activiti:formProperty id="FormProperty_2khp7qn" name="Olá" type="string" />
      </bpmn2:extensionElements>
      <bpmn2:incoming>SequenceFlow_0fage2o</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_0yvfjuh</bpmn2:outgoing>
    </bpmn2:userTask>
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="TesteAnd">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="412" y="240" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ExclusiveGateway_1u8iq8b_di" bpmnElement="ExclusiveGateway_1u8iq8b" isMarkerVisible="true">
        <dc:Bounds x="498" y="233" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_1nevhlf_di" bpmnElement="SequenceFlow_1nevhlf">
        <di:waypoint x="448" y="258" />
        <di:waypoint x="498" y="258" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="EndEvent_0fkrjbp_di" bpmnElement="EndEvent_0fkrjbp">
        <dc:Bounds x="598" y="240" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_040s2zr_di" bpmnElement="SequenceFlow_040s2zr">
        <di:waypoint x="548" y="258" />
        <di:waypoint x="598" y="258" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="SequenceFlow_0fage2o_di" bpmnElement="SequenceFlow_0fage2o">
        <di:waypoint x="523" y="283" />
        <di:waypoint x="523" y="368" />
        <di:waypoint x="598" y="368" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="EndEvent_1v1zpde_di" bpmnElement="EndEvent_1v1zpde">
        <dc:Bounds x="748" y="350" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_0yvfjuh_di" bpmnElement="SequenceFlow_0yvfjuh">
        <di:waypoint x="698" y="368" />
        <di:waypoint x="748" y="368" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="UserTask_12obkqm_di" bpmnElement="Task_04n6q8e">
        <dc:Bounds x="598" y="328" width="100" height="80" />
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

And then (after moving something around to make “changes”) i downloaded the resultant bpmn and the formalExpression was without CDATA:

<?xml version="1.0" encoding="UTF-8"?>
<bpmn2:definitions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmn2="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:activiti="http://activiti.org/bpmn" id="sample-diagram" targetNamespace="http://bpmn.io/schema/bpmn" xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd">
  <bpmn2:process id="TesteAnd" name="TesteAnd" isExecutable="true">
    <bpmn2:startEvent id="StartEvent_1">
      <bpmn2:outgoing>SequenceFlow_1nevhlf</bpmn2:outgoing>
    </bpmn2:startEvent>
    <bpmn2:exclusiveGateway id="ExclusiveGateway_1u8iq8b" default="SequenceFlow_0fage2o">
      <bpmn2:incoming>SequenceFlow_1nevhlf</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_040s2zr</bpmn2:outgoing>
      <bpmn2:outgoing>SequenceFlow_0fage2o</bpmn2:outgoing>
    </bpmn2:exclusiveGateway>
    <bpmn2:sequenceFlow id="SequenceFlow_1nevhlf" sourceRef="StartEvent_1" targetRef="ExclusiveGateway_1u8iq8b" />
    <bpmn2:endEvent id="EndEvent_0fkrjbp">
      <bpmn2:incoming>SequenceFlow_040s2zr</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_040s2zr" sourceRef="ExclusiveGateway_1u8iq8b" targetRef="EndEvent_0fkrjbp">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">${a == 2 &amp;&amp; b == 3}</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>
    <bpmn2:sequenceFlow id="SequenceFlow_0fage2o" sourceRef="ExclusiveGateway_1u8iq8b" targetRef="Task_04n6q8e" />
    <bpmn2:endEvent id="EndEvent_1v1zpde">
      <bpmn2:incoming>SequenceFlow_0yvfjuh</bpmn2:incoming>
    </bpmn2:endEvent>
    <bpmn2:sequenceFlow id="SequenceFlow_0yvfjuh" sourceRef="Task_04n6q8e" targetRef="EndEvent_1v1zpde" />
    <bpmn2:userTask id="Task_04n6q8e" activiti:async="true">
      <bpmn2:extensionElements>
        <activiti:formProperty id="FormProperty_2khp7qn" name="Olá" type="string" />
      </bpmn2:extensionElements>
      <bpmn2:incoming>SequenceFlow_0fage2o</bpmn2:incoming>
      <bpmn2:outgoing>SequenceFlow_0yvfjuh</bpmn2:outgoing>
    </bpmn2:userTask>
  </bpmn2:process>
  <bpmndi:BPMNDiagram id="BPMNDiagram_1">
    <bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="TesteAnd">
      <bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
        <dc:Bounds x="381" y="350" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNShape id="ExclusiveGateway_1u8iq8b_di" bpmnElement="ExclusiveGateway_1u8iq8b" isMarkerVisible="true">
        <dc:Bounds x="498" y="233" width="50" height="50" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_1nevhlf_di" bpmnElement="SequenceFlow_1nevhlf">
        <di:waypoint x="417" y="368" />
        <di:waypoint x="523" y="368" />
        <di:waypoint x="523" y="283" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="EndEvent_0fkrjbp_di" bpmnElement="EndEvent_0fkrjbp">
        <dc:Bounds x="598" y="240" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_040s2zr_di" bpmnElement="SequenceFlow_040s2zr">
        <di:waypoint x="548" y="258" />
        <di:waypoint x="598" y="258" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNEdge id="SequenceFlow_0fage2o_di" bpmnElement="SequenceFlow_0fage2o">
        <di:waypoint x="523" y="283" />
        <di:waypoint x="523" y="368" />
        <di:waypoint x="598" y="368" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="EndEvent_1v1zpde_di" bpmnElement="EndEvent_1v1zpde">
        <dc:Bounds x="748" y="350" width="36" height="36" />
      </bpmndi:BPMNShape>
      <bpmndi:BPMNEdge id="SequenceFlow_0yvfjuh_di" bpmnElement="SequenceFlow_0yvfjuh">
        <di:waypoint x="698" y="368" />
        <di:waypoint x="748" y="368" />
      </bpmndi:BPMNEdge>
      <bpmndi:BPMNShape id="UserTask_12obkqm_di" bpmnElement="Task_04n6q8e">
        <dc:Bounds x="598" y="328" width="100" height="80" />
      </bpmndi:BPMNShape>
    </bpmndi:BPMNPlane>
  </bpmndi:BPMNDiagram>
</bpmn2:definitions>

Can you guide me trought where is this being done? i have an editing option in my project and i can’t really be editing every sequence flow in order to CDATA appear again.

Any suggestion would be welcome… ty

The behavior you’re observing is correct. As of v0.31.0 bpmn-js will use entity encoding instead of CDATA. Most BPMN tools do that. CDATA has a few issues regarding interoperability which is why we don’t use it anymore. Both escaped entities and CDATA should have the same outcome when being parsed anyway. Why is this relevant for you?

1 Like

The bpmn generated is being deployed to Activiti and it complains about not having the CDATA in conditionalExpressions.

What exactly does Activiti complain about (attach stack traces and error logs)? What steps do you undertake to deploy to it?

Don’t need to talk about the deploy itself, since it works perfectly in other situations.

Activiti throws an exception if the bpmn contains expressions with an “&” (that is sent as &amp;):

2018-12-12 09:45:10,647 ERROR BpmnXMLConverter     [qtp1824379333-91    ] Error processing BPMN document
javax.xml.stream.XMLStreamException: ParseError at [row,col]:[30,78]
Message: The entity name must immediately follow the '&' in the entity reference.
        at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.next(XMLStreamReaderImpl.java:604)
        at com.sun.org.apache.xerces.internal.impl.XMLStreamReaderImpl.getElementText(XMLStreamReaderImpl.java:865)
        at org.activiti.bpmn.converter.child.ConditionExpressionParser.parseChildElement(ConditionExpressionParser.java:34)
        at org.activiti.bpmn.converter.util.BpmnXMLUtil.parseChildElements(BpmnXMLUtil.java:126)
        at org.activiti.bpmn.converter.BaseBpmnXMLConverter.parseChildElements(BaseBpmnXMLConverter.java:249)
        at org.activiti.bpmn.converter.BaseBpmnXMLConverter.parseChildElements(BaseBpmnXMLConverter.java:240)
        at org.activiti.bpmn.converter.SequenceFlowXMLConverter.convertXMLToElement(SequenceFlowXMLConverter.java:47)
        at org.activiti.bpmn.converter.BaseBpmnXMLConverter.convertToBpmnModel(BaseBpmnXMLConverter.java:84)
        at org.activiti.bpmn.converter.BpmnXMLConverter.convertToBpmnModel(BpmnXMLConverter.java:430)
 <bpmn2:sequenceFlow id="SequenceFlow_0n3qmsm" sourceRef="ExclusiveGateway_1pxlfg4" targetRef="Task_1nf8qhh">
      <bpmn2:conditionExpression xsi:type="bpmn2:tFormalExpression">${a &gt; 2 &amp;&amp; a &lt; 3}</bpmn2:conditionExpression>
    </bpmn2:sequenceFlow>

If it doesn’t contain an & or if the & is inside a CDATA it wont throw an exception, parsing the bpmn deployed as it should.

Thanks for posting the relevant details. We’ll give this another look.

2 Likes

hi raquel,
i’m using activiti also and i have a question
how can i reference the conditionExpression to the modelProperty from the sequenceFlow businessObject
for exemple if open the diagram below in my designer, select the sequencFlow and write ${foo == “bar”} in the textBox area the result i get is ${a == 2 && b == 3}=${foo == bar}
i set the model property to => modelProperty: element.businessObject.conditionExpression.body so i’m getting the value of the condition as a reference
any help please
best regards