如何在MuleSoft DataWeave中移除XML命名空间
如何在DataWeave 2.0中移除XML的所有命名空间?
我在使用MuleSoft DataWeave转换XML消息时,想要移除所有的xmlns命名空间,但当前的转换结果里仍残留着命名空间声明。以下是我的具体场景:
输入XML
<?xml version='1.0' encoding='UTF-8'?> <Entries xmlns="http://www.example.nl/Entries" type="Catalog" name="xxx Catalog" exportDate="2018-01-18T10:08:27.609Z"> <Entry id="264063" deleted="0" creationDate="2017-05-26T14:26:09.511Z" lastModifiedDate="2017-10-13T22:46:39.000Z"> <Attributes> <Attribute> <MetadataPath>Just an example 1</MetadataPath> <Locale/> </Attribute> <Attribute> <MetadataPath>Just an example 2</MetadataPath> <Locale>en_GB</Locale> </Attribute> </Attributes> <Categories> <Category> <Hierarchy>GPC_Hierarchy</Hierarchy> <Id>999999</Id> </Category> <Category> <Hierarchy>GPC_xx_Hierarchy</Hierarchy> <Id>999998</Id> </Category> </Categories> <Specs> <Spec>Validatie Spec</Spec> <Spec>Item Spec</Spec> </Specs> </Entry> </Entries>
当前使用的DataWeave代码
%dw 2.0 var x = payload.Entries output application/xml encoding="utf-8" --- { Entry @('type': x.@'type', name: x.@name, exportDate: x.@exportDate, id: x.Entry.@id, deleted: x.Entry.@deleted, creationDate: x.Entry.@creationDate, lastModifiedDate: x.Entry.@lastModifiedDate ) : {(x.Entry.Attributes ), ( Categories: (x.Entry.Categories) ), ( Specs: (x.Entry.Specs) ) } }
当前转换结果(仍有残留命名空间)
<?xml version='1.0' encoding='UTF-8'?> <Entry type="Catalog" name="xxx Catalog" exportDate="2018-01-18T10:08:27.609Z" id="264063" deleted="0" creationDate="2017-05-26T14:26:09.511Z" lastModifiedDate="2017-10-13T22:46:39.000Z"> <Attribute xmlns="http://www.example.nl/Entries"> <MetadataPath>Just an example 1</MetadataPath> <Locale/> </Attribute> <Attribute xmlns="http://www.example.nl/Entries"> <MetadataPath>Just an example 2</MetadataPath> <Locale>en_GB</Locale> </Attribute> <Categories> <Category xmlns="http://www.example.nl/Entries"> <Hierarchy>GPC_Hierarchy</Hierarchy> <Id>999999</Id> </Category> <Category xmlns="http://www.example.nl/Entries"> <Hierarchy>GPC_xx_Hierarchy</Hierarchy> <Id>999998</Id> </Category> </Categories> <Specs> <Spec xmlns="http://www.example.nl/Entries">Validatie Spec</Spec> <Spec xmlns="http://www.example.nl/Entries">Item Spec</Spec> </Specs> </Entry>
我不想完全重写整个消息结构,想知道有没有类似output application/xml removeAllNamespaces这样的简洁语法来一次性移除所有命名空间?
解决方案:递归移除所有命名空间
遗憾的是,DataWeave 2.0并没有提供直接的removeAllNamespaces输出参数,但我们可以通过递归遍历XML节点并移除命名空间的方式实现需求,而且不需要完全重写消息结构。这里有几种实用的方法:
方法1:通用递归函数处理全节点
写一个通用递归函数,遍历XML的每个元素和属性,自动移除命名空间:
%dw 2.0 output application/xml encoding="utf-8" // 递归函数:移除节点与属性的命名空间 fun removeNamespaces(node) = if (node is Object) node mapObject (value, key) -> { // 提取不带命名空间的节点名 (key as String splitBy ":")[-1] @(removeNamespaces(key.@)): if (value is Array) value map removeNamespaces($) else removeNamespaces(value) } else if (node is Array) node map removeNamespaces($) else node --- // 对整个payload应用函数后,提取需要的结构 removeNamespaces(payload).Entries
这个函数会自动处理所有层级的元素和属性,把带命名空间的节点名(如ns:Attribute)转换成纯节点名Attribute,同时清除所有xmlns声明。
方法2:基于现有转换代码快速修改
如果你想保留当前的转换逻辑,只需对最终生成的对象应用命名空间移除即可:
%dw 2.0 var x = payload.Entries output application/xml encoding="utf-8" fun removeNamespaces(node) = if (node is Object) node mapObject (value, key) -> { (key as String splitBy ":")[-1] @(removeNamespaces(key.@)): if (value is Array) value map removeNamespaces($) else removeNamespaces(value) } else if (node is Array) node map removeNamespaces($) else node --- removeNamespaces({ Entry @('type': x.@'type', name: x.@name, exportDate: x.@exportDate, id: x.Entry.@id, deleted: x.Entry.@deleted, creationDate: x.Entry.@creationDate, lastModifiedDate: x.Entry.@lastModifiedDate ) : {(x.Entry.Attributes ), ( Categories: (x.Entry.Categories) ), ( Specs: (x.Entry.Specs) ) } })
方法3:用namespace函数清空命名空间
另一种更简洁的方式是利用namespace函数,直接为所有节点指定空命名空间:
%dw 2.0 output application/xml encoding="utf-8" --- namespace "" payload.Entries.*Entry map ((entry) -> { Entry @( type: payload.Entries.@type, name: payload.Entries.@name, exportDate: payload.Entries.@exportDate, id: entry.@id, deleted: entry.@deleted, creationDate: entry.@creationDate, lastModifiedDate: entry.@lastModifiedDate ): { (entry.Attributes.*Attribute), Categories: entry.Categories.*Category, Specs: entry.Specs.*Spec } })
最终效果
以上方法都会生成无任何命名空间的XML结果,示例如下:
<?xml version='1.0' encoding='UTF-8'?> <Entry type="Catalog" name="xxx Catalog" exportDate="2018-01-18T10:08:27.609Z" id="264063" deleted="0" creationDate="2017-05-26T14:26:09.511Z" lastModifiedDate="2017-10-13T22:46:39.000Z"> <Attribute> <MetadataPath>Just an example 1</MetadataPath> <Locale/> </Attribute> <Attribute> <MetadataPath>Just an example 2</MetadataPath> <Locale>en_GB</Locale> </Attribute> <Categories> <Category> <Hierarchy>GPC_Hierarchy</Hierarchy> <Id>999999</Id> </Category> <Category> <Hierarchy>GPC_xx_Hierarchy</Hierarchy> <Id>999998</Id> </Category> </Categories> <Specs> <Spec>Validatie Spec</Spec> <Spec>Item Spec</Spec> </Specs> </Entry>
内容的提问来源于stack exchange,提问作者Ben
相关产品推荐
相关产品推荐

