Akshit Malhotra
Akshit Malhotra

Reputation: 1

Getting Error on adding xml code dynamically in the current rendered XML

Rendered the BPMN flow diagram on react s UI using bpmn modeler The flow is rendered from xml on the UI. XML is rendered already and on the rendered xml we want to add xml code dynamically, I am having piece of xml code already just only want to append (dynamically) the xml as string and then insert the code and re render again.

Approach-1 (using DOMParser)

Explanation of the code is below:

DiagramService.getCurrentDiagramXml() is called to retrieve the XML representation of the current BPMN diagram. It returns a promise that resolves to the XML string.

The retrieved XML string is then parsed using DOMParser() to create an XML document object (xmlDoc). The parent node where the custom subprocess will be appended is identified using querySelector() based on its ID (Process_1).

The XML representing the custom subprocess (childSubProcess) is defined as a string. This subprocess contains various BPMN elements such as tasks, events, and sequence flows.

Another DOMParser() is used to create a document fragment (fragment) from the XML string representing the custom subprocess.

Append each child node of the document fragment to the parent node. After appending the custom subprocess, the modified XML document (xmlDoc) is serialized back to a string using XMLSerializer().

The resulting XML string (newXml).

Finally, DiagramService.renderDiagramCanvas(newXml) is called to render the modified BPMN diagram. Note : We have attributes of the task node as in the format voice:voiceTaskType , voice:voiceFileInfo

Code:

const insertCustomSubProcess = async () => {
try {
const diagramXML = await DiagramService.getCurrentDiagramXml();

// Parsing diagramXML
let parser = new DOMParser();
let xmlDoc = parser.parseFromString(diagramXML, "text/xml" );

// Find the parent node
let parentNode = xmlDoc.querySelector(process[id= “Process_1” ]);

// xml code names childSubProcess that we need to append
const childSubProcess = <subProcess id= “Activity_0009n6k” name= “Greetings” >`

<incoming>Flow_1s78vky</incoming>
<outgoing>Flow_16nzjzj</outgoing>
<task id= "Activity_08gzhgi" name= "Greetings" voice:taskType= "playVoiceFile" voice:voiceFileInfo= "{" en ":

{" filePath ":" welcome "," ttsText ":" "," gender ":" "," playSpeed ":" "," voiceFileType ":" libraryFile "," fileUrl ":" "," fileSize ":" "}," es ":{" filePath ":" es/welcome "," ttsText ":" "," gender ":" "," playSpeed ":" ",

" voiceFileType ":" libraryFile "," fileUrl ":" "," fileSize ":" "," id ":" "," option ":" "}}" session:stepName= "PlayGreeting" >

<incoming>Flow_1we1xkv</incoming>
<outgoing>Flow_0ordxhx</outgoing>
</task>
<startEvent id= "Event_0fwsfrr" name= "Greetings_Start_1" >
<outgoing>Flow_1we1xkv</outgoing>
</startEvent>
<sequenceFlow id= "Flow_1we1xkv" sourceRef= "Event_0fwsfrr" targetRef= "Activity_08gzhgi" />
<intermediateThrowEvent id= "Event_12tlhn0" name= "Greetings_Intermediate_1" >
<incoming>Flow_0ordxhx</incoming>
</intermediateThrowEvent>

<sequenceFlow id= "Flow_0ordxhx" sourceRef= "Activity_08gzhgi" targetRef= "Event_12tlhn0" />
</subProcess>;`

// Create a document fragment for the new child XML
let fragment = parser.parseFromString(childSubProcess, "text/xml" );

// Append the new child XML to the parent node
while (fragment.firstChild) {
parentNode.appendChild(fragment.firstChild);
}

// Serialize the modified XML back to a string
let serializer = new XMLSerializer();
let newXml = serializer.serializeToString(xmlDoc);
console.log( "newXml" , newXml);
DiagramService.renderDiagramCanvas(newXml);

} catch (error) {
// log the error here
}
}

Result of Approach-1 :

This page contains the following errors: error on line 4 at column 683: Namespace prefix voice for taskType on task is not defined

Below is a rendering of the page up to the first error. Flow_1s78vky Flow_16nzjzj voice:voiceTaskType and voice:voiceFileInfo are the attributes of the node name task

enter image description here

Approach-2 (using string manilpulation)

Code:

const insertCustomSubProcess = async () => {
try {
  const diagramXML = await DiagramService.getCurrentDiagramXml();
  // Find the position where we want to insert the sub-process
  const insertIndex = diagramXML.indexOf('</process>');

  // Define the sub-process XML
  const childSubProcess = `<subProcess id="Activity_0009n6K" name="Hello">
        <incoming>Flow_1s78vky</incoming>
        <outgoing>Flow_16nzjzj</outgoing>
        <task id="Activity_08gzhgi" name="Hello" voice:taskType="playVoiceFile" voice:voiceFileInfo="{"en":{"filePath":"welcome","ttsText":"","gender":"","playSpeed":"","voiceFileType":"libraryFile","fileUrl":"","fileSize":""},"es":{"filePath":"es/welcome","ttsText":"","gender":"","playSpeed":"","voiceFileType":"libraryFile","fileUrl":"","fileSize":"","id":"","option":""}}" session:stepName="PlayGreeting">
            <incoming>Flow_1we1xkv</incoming>
            <outgoing>Flow_0ordxhx</outgoing>
        </task>
        <startEvent id="Event_0fwsfrr" name="Hello_Start_1">
            <outgoing>Flow_1we1xkv</outgoing>
        </startEvent>
        <sequenceFlow id="Flow_1we1xkv" sourceRef="Event_0fwsfrr" targetRef="Activity_08gzhgi" />
        <intermediateThrowEvent id="Event_12tlhn0" name="Hello_Intermediate_1">
            <incoming>Flow_0ordxhx</incoming>
        </intermediateThrowEvent>
        <sequenceFlow id="Flow_0ordxhx" sourceRef="Activity_08gzhgi" targetRef="Event_12tlhn0" />
    </subProcess>`;

  // Insert the sub-process XML into the diagramXML at the defined position
  const newDiagramXML = diagramXML.slice(0, insertIndex) + childSubProcess + diagramXML.slice(insertIndex);
  console.log("newXml", newDiagramXML);
  // Render the modified XML
  await DiagramService.renderDiagramCanvas(newDiagramXML);

} catch (error) {
  console.error("Error occurred:", error);
  // Handle the error gracefully, e.g., show a message to the user
}

}

Result of Approach-2:

XML gets updated but due to its internal creation of co-ordinates of the flow , it is not rendering .Below is the xml code for co ordinates that bpmn generates own its own.

<bpmndi:BPMNShape id="Activity_0009n6k_di" bpmnElement="Activity_0009n6k" isExpanded="false">
    <omgdc:Bounds x="-1482" y="-2765" width="270" height="120" />
  </bpmndi:BPMNShape>

Upvotes: 0

Views: 99

Answers (0)

Related Questions