如何在DataWeave中实现XML内容转字符串嵌入JSON输出,并动态处理未知结构的XML数据
Got it, let's tackle this problem. The core challenge here is dynamically converting unknown XML structures into JSON, while turning specific XML elements into their raw XML string representations to avoid data loss. Here's a complete solution that builds on your existing code and adds the critical XML stringification logic:
%dw 2.0 import * from dw::core::Types import mergeWith from dw::core::Objects import * from dw::core::XML // Import XML utilities for string conversion input payload xml output application/json // Separate scalar and object keys from Report_Entry var literalKeys = (namesOf(payload.Report_Data.Report_Entry) distinctBy $) filter ((item) -> not isObjectType(typeOf(payload.Report_Data.Report_Entry[item]))) var objectKeys = (namesOf(payload.Report_Data.Report_Entry) distinctBy $) filter ((item) -> isObjectType(typeOf(payload.Report_Data.Report_Entry[item]))) // Extract scalar values as-is (kept as native JSON types) var justTheScalars = payload.Report_Data.Report_Entry filterObject((value, key) -> literalKeys includes key ) // Extract object elements, group them by key, then convert to concatenated XML strings var xmlStringifiedObjects = payload.Report_Data.Report_Entry filterObject((value, key) -> objectKeys includes key) groupBy ((item, index) -> index) // Group elements by their key name mapObject ((elementsArray, key) -> { // Convert each element to XML string, then join all into one continuous string (key): elementsArray map (elem) -> dw::core::XML::write(elem, {skipXmlDeclaration: true}) joinBy "" }) // Merge scalars and stringified XML objects into the final JSON output --- justTheScalars mergeWith xmlStringifiedObjects
Key Breakdown of the Solution:
XML-to-String Conversion
We usedw::core::XML::write()to serialize XML nodes into raw strings. TheskipXmlDeclaration: trueparameter removes the default<?xml version="1.0"?>header, which aligns with your expected output format that only includes the element content.Dynamic Structure Handling
- We retain your original logic for dynamically detecting keys in
Report_EntryusingnamesOf(), then split them into scalars (text, numbers, etc.) and objects (nested XML elements). - Scalar values are preserved as native JSON types (strings, numbers) to maintain compatibility with downstream workflows.
- We retain your original logic for dynamically detecting keys in
Handling Multiple Elements Under the Same Key
- For object-type keys, we first filter and group all matching elements by their key name.
- Each element in the group is converted to an XML string, then joined together into a single string. This handles cases where you have multiple elements under the same key (like the two
<book>elements in your example) by concatenating their XML representations.
Example Test Case:
If your input XML looks like this:
<Report_Data> <Report_Entry> <book category="cooking"> <title lang="en">Everyday Italian</title> <author>Giada De Laurentiis</author> <year>2005</year> <price>30.00</price> </book> <book category="children"> <title lang="en">Harry Potter</title> <author>J K. Rowling</author> <year>2005</year> <price>29.99</price> </book> <storeLocation>New York</storeLocation> </Report_Entry> </Report_Data>
The output JSON will be:
{ "storeLocation": "New York", "book": "<book category=\"cooking\"><title lang=\"en\">Everyday Italian</title><author>Giada De Laurentiis</author><year>2005</year><price>30.00</price></book><book category=\"children\"><title lang=\"en\">Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book>" }
This solution automatically adapts to any unknown structure in Report_Entry, so you don’t need to hardcode element names. It preserves all XML attributes and nested structure by converting objects to raw XML strings, while keeping simple values as native JSON types.
内容的提问来源于stack exchange,提问作者rpazos98

