WSO2 MI 4.1.0移除DSS输出XML声明标签及解决迭代问题
问题描述
我通过DSS从数据库获取数据并返回XML格式结果,但流程无法进入Iterate中介器。移除XML声明标签<?xml version='1.0' encoding='UTF-8'?>后,在线XPath工具能正常生成表达式。请问是否必须移除该标签?如果需要,在WSO2 MI 4.1.0中该如何操作?
数据库调用示例输出
<?xml version='1.0' encoding='utf-8'?> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <Entries xmlns="TotscoDS"> <statusCodePresent>429 </statusCodePresent> <statusCodePresent>429 </statusCodePresent> <statusCodePresent>429 </statusCodePresent> <statusCodePresent>429 </statusCodePresent> <statusCodePresent>429 </statusCodePresent> </Entries> </soapenv:Body> </soapenv:Envelope>
当前序列代码
<payloadFactory media-type="xml"> <format> <getStates> <msID>$1</msID> </getStates> </format> <args> <arg evaluator="xml" expression="$ctx:MI_ID"/> </args> </payloadFactory> <property name="messageType" scope="axis2" type="STRING" value="text/xml"/> <header name="Action" scope="default" value="retrieveStateDetails"/> <call> <endpoint key="TotscoEP" /> </call> <log level="full" /> <iterate expression="//Entries" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <target> <sequence> <property expression="//statusCodePresent/text()" name="statusCodePresent" scope="default" type="STRING"/> <log level="custom"> <property expression="fn:concat($ctx:HUBMessageID,' : StatusCode = ',$ctx:statusCodePresent)" name="Message"/> </log> <filter regex="false" source="boolean(get-property('statusCodePresent'))"> <then> <log level="custom"> <property expression="fn:concat($ctx:HUBMessageID,' : No Status Code from RCP')" name="Message"/> </log> </then> <else/> </filter> </sequence> </target> </iterate>
解决方案
1. XML声明标签并非必须移除
问题核心不是XML声明,而是命名空间未正确处理。返回的<Entries>节点属于TotscoDS命名空间,而你的Iterate表达式//Entries未指定该命名空间,导致XPath无法匹配目标节点,流程因此无法进入Iterate中介器。
2. 正确处理命名空间的Iterate配置
修改Iterate中介器,添加TotscoDS命名空间声明,并在XPath表达式中使用对应前缀:
<iterate expression="//ts:Entries" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ts="TotscoDS"> <target> <sequence> <!-- 获取statusCodePresent时同样需要指定命名空间 --> <property expression="//ts:statusCodePresent/text()" name="statusCodePresent" scope="default" type="STRING"/> <log level="custom"> <property expression="fn:concat($ctx:HUBMessageID,' : StatusCode = ',$ctx:statusCodePresent)" name="Message"/> </log> <filter regex="false" source="boolean(get-property('statusCodePresent'))"> <then> <log level="custom"> <property expression="fn:concat($ctx:HUBMessageID,' : No Status Code from RCP')" name="Message"/> </log> </then> <else/> </filter> </sequence> </target> </iterate>
3. 若确需移除XML声明的操作方法
如果因特殊需求必须移除XML声明,可在WSO2 MI 4.1.0中通过以下两种方式实现:
方式一:使用PayloadFactory重构Payload
在Call中介器之后,用PayloadFactory重新生成不含XML声明的XML内容:
<call> <endpoint key="TotscoEP" /> </call> <payloadFactory media-type="xml"> <format> <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv:Body> <Entries xmlns="TotscoDS"> <statusCodePresent>$1</statusCodePresent> <!-- 按需重复节点,若节点数量不固定建议用方式二 --> </Entries> </soapenv:Body> </soapenv:Envelope> </format> <args> <arg evaluator="xml" expression="//ts:statusCodePresent/text()" xmlns:ts="TotscoDS"/> </args> </payloadFactory>
方式二:使用Script中介器修改消息内容
通过Groovy脚本直接移除XML声明:
<call> <endpoint key="TotscoEP" /> </call> <script language="groovy"><![CDATA[ def payload = mc.getPayloadXML().toString(); // 匹配并移除XML声明部分 def cleanedPayload = payload.replaceFirst(/<\?xml[^>]+\?>/, ""); mc.setPayloadXML(cleanedPayload); ]]></script>
内容的提问来源于stack exchange,提问作者Sumathi M
相关产品推荐
相关产品推荐

