SAP CPI:使用Groovy在指定XML节点后追加节点失败求助
SAP CPI Groovy脚本节点插入问题解决方法
问题说明
在SAP CPI中尝试通过Groovy脚本,将包含SenderBusinessSystemID和RecipientBusinessSystemID的<MessageHeader>节点插入到XML的<BusinessPartnerSUITEBulkReplicateRequest>节点内部、第一个<BusinessPartnerSUITEReplicateRequestMessage>节点之前,但操作失败。直接将节点追加到消息末尾可正常执行,尝试通过命名空间定位目标节点也未成功。
原始XML
<?xml version="1.0" encoding="UTF-8"?> <ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge"> <ns0:Message1> <ns1:BusinessPartnerSUITEBulkReplicateRequest xmlns:ns1="http://sap.com/xi/SAPGlobal20/Global"> <BusinessPartnerSUITEReplicateRequestMessage> <BusinessPartner actionCode="04" addressInformationListCompleteTransmissionIndicator="true" roleListCompleteTransmissionIndicator="true"> <UUID>b26a8b91-da4d-4761-bbc5-4bf704f0eb4a</UUID> <InternalID>00000016</InternalID> <CategoryCode>2</CategoryCode> <AddressInformation actionCode="04"> <UUID>3ccc411f-5ff3-4f78-a38a-11c4eb45d30c</UUID> <Address actionCode="04" emailListCompleteTransmissionIndicator="true" facsimileListCompleteTransmissionIndicator="true"> <CommunicationPreference actionCode="04"> <CorrespondenceLanguageCode>DE</CorrespondenceLanguageCode> </CommunicationPreference> <Email actionCode="04" eMailUsageListCompleteTransmissionIndicator="true"> <URI>test@sap.com</URI> <UsageDeniedIndicator>false</UsageDeniedIndicator> <EmailUsage actionCode="04"> <Usage> <Code>AD_DEFAULT</Code> </Usage> <DefaultIndicator>true</DefaultIndicator> </EmailUsage> </Email> <PostalAddress actionCode="04"> <CountryCode>UA</CountryCode> <RegionCode /> <CityName>Bönen</CityName> <StreetPostalCode>59199</StreetPostalCode> <StreetName>Siemensstraße</StreetName> <HouseID>10</HouseID> <POBoxID /> </PostalAddress> </Address> </AddressInformation> <Common actionCode="04"> <Organisation> <Name> <FirstLineName>testfirstname</FirstLineName> <SecondLineName>testlastname</SecondLineName> </Name> </Organisation> </Common> <Role actionCode="04"> <RoleCode>ZCU005</RoleCode> </Role> </BusinessPartner> </BusinessPartnerSUITEReplicateRequestMessage> <BusinessPartnerSUITEReplicateRequestMessage> <BusinessPartner actionCode="04" addressInformationListCompleteTransmissionIndicator="true" commonListCompleteTransmissionIndicator="true" roleListCompleteTransmissionIndicator="true"> <UUID>ace66c2d-44a8-4238-b411-53ad2520d7b4</UUID> <InternalID>DUMMY</InternalID> <CategoryCode>1</CategoryCode> <AddressInformation actionCode="04"> <UUID>eb16d063-faf5-4fbb-a67c-514216ee162f</UUID> <Address actionCode="04" emailListCompleteTransmissionIndicator="true" facsimileListCompleteTransmissionIndicator="true"> <CommunicationPreference actionCode="04"> <CorrespondenceLanguageCode>DE</CorrespondenceLanguageCode> </CommunicationPreference> <PersonName actionCode="04"> <Name> <GivenName>DUMMYfirstname</GivenName> <FamilyName>DUMMYlastname</FamilyName> </Name> </PersonName> </Address> </AddressInformation> <Role actionCode="04"> <RoleCode>BUP001</RoleCode> </Role> </BusinessPartner> </BusinessPartnerSUITEReplicateRequestMessage> </ns1:BusinessPartnerSUITEBulkReplicateRequest> </ns0:Message1> </ns0:Messages>
目标追加节点
<MessageHeader> <SenderBusinessSystemID>${sender}</SenderBusinessSystemID> <RecipientBusinessSystemID>${receiver}</RecipientBusinessSystemID> </MessageHeader>
当前Groovy脚本
import com.sap.gateway.ip.core.customdev.util.Message; import java.util.HashMap; import groovy.xml.XmlUtil; def Message processData(Message message) { def ns0 = new groovy.xml.Namespace('http://sap.com/xi/XI/SplitAndMerge'); def ns1 = new groovy.xml.Namespace('http://sap.com/xi/SAPGlobal20/Global'); def receiver = message.getProperties().get("Receiver"); def sender = message.getProperties().get("Sender"); def body = message.getBody(java.lang.String) as String; def newString = "<MessageHeader><SenderBusinessSystemID>"+sender+"</SenderBusinessSystemID><RecipientBusinessSystemID>"+receiver+"</RecipientBusinessSystemID></MessageHeader>" def response= new XmlSlurper().parseText(body) def newNode = new XmlSlurper().parseText(newString) response.Messages[0].Message1[0].BusinessPartnerSUITEBulkReplicateRequest[0].appendNode(newNode); response.appendNode(newNode); def String outxml = groovy.xml.XmlUtil.serialize(response) message.setBody(outxml); return message; }
解决思路及修正脚本
问题分析
- 命名空间未正确使用:
BusinessPartnerSUITEBulkReplicateRequest属于ns1命名空间,直接通过节点名访问无法定位到目标节点,必须结合命名空间进行查找。 - 插入位置错误:
appendNode方法是将节点追加到目标节点的子节点末尾,而需求是插入到第一个BusinessPartnerSUITEReplicateRequestMessage之前,需要使用insertBefore方法。 - 节点创建方式优化:使用
MarkupBuilder创建新节点比解析字符串更可靠,避免潜在的XML格式问题。
修正后的Groovy脚本
import com.sap.gateway.ip.core.customdev.util.Message; import groovy.xml.XmlSlurper; import groovy.xml.XmlUtil; import groovy.xml.MarkupBuilder; import java.io.StringWriter; def Message processData(Message message) { // 定义命名空间 def ns0 = new groovy.xml.Namespace('http://sap.com/xi/XI/SplitAndMerge'); def ns1 = new groovy.xml.Namespace('http://sap.com/xi/SAPGlobal20/Global'); // 获取Sender和Receiver属性 def receiver = message.getProperties().get("Receiver"); def sender = message.getProperties().get("Sender"); // 解析原始XML def body = message.getBody(java.lang.String) as String; def xmlSlurper = new XmlSlurper(false, false); def response = xmlSlurper.parseText(body); // 使用MarkupBuilder创建MessageHeader节点 def writer = new StringWriter(); def markupBuilder = new MarkupBuilder(writer); markupBuilder.MessageHeader { SenderBusinessSystemID(sender) RecipientBusinessSystemID(receiver) } def newNode = new XmlSlurper().parseText(writer.toString()); // 定位目标父节点:BusinessPartnerSUITEBulkReplicateRequest def bulkRequestNode = response[ns0.Message1][ns1.BusinessPartnerSUITEBulkReplicateRequest][0]; // 定位第一个要插入的位置节点:BusinessPartnerSUITEReplicateRequestMessage def firstRequestMessageNode = bulkRequestNode.BusinessPartnerSUITEReplicateRequestMessage[0]; // 在第一个RequestMessage节点前插入新节点 firstRequestMessageNode.insertBefore(newNode); // 序列化XML并设置回消息体 def outxml = XmlUtil.serialize(response); message.setBody(outxml); return message; }
关键点说明
- 命名空间定位:通过
response[ns0.Message1][ns1.BusinessPartnerSUITEBulkReplicateRequest]正确定位到目标父节点,避免因命名空间缺失导致的节点查找失败。 - 插入方法:使用
insertBefore方法将新节点插入到指定节点的前面,满足需求中的位置要求。 - 节点创建:
MarkupBuilder更适合动态生成XML节点,减少字符串拼接可能带来的错误。
内容的提问来源于stack exchange,提问作者Desislava Tsoneva
相关产品推荐
相关产品推荐

