user2519508
user2519508

Reputation: 1

dataweave 2.0 transformation

I have a XML file which has nested elements and few elements has attributes to that. I want to convert this XML to json using dataweave 2.0 and the json has to contain the attributes.

Using the json generated from previous step, I want to recreate the original XML

Ex: <elem1>
<elem2 attr=Val>
<elem3 attr=Val>
</elem3>
</elem2>
</elem1>

Thanks in advance

Upvotes: 0

Views: 654

Answers (3)

Salim Khan
Salim Khan

Reputation: 4303

Using Christian's approach , you could update the script to remove "@" from the attribute keys:

%dw 2.0
output application/xml

fun collectAttributes(elem:Object) = 
    elem filterObject ((value, key, index) -> key contains  "@" )

fun putAttributes(elem: Object) =
    elem mapObject ((value, key, index) -> value match {
        case is Object -> do {
            var attr = (collectAttributes(value))
            var attrfinal = attr mapObject {
                ($$ replace "@" with ""):(($))
            }
            var withoutAttr = value -- attr
            ---
            (key) @((attrfinal)): 
                if (keysOf(withoutAttr) contains "__text" as Key)
                    withoutAttr."__text" 
                else 
                    putAttributes(withoutAttr)
        }
        else -> (key): value
      })
        
---
putAttributes(payload)

Upvotes: 2

short stack stevens
short stack stevens

Reputation: 692

You could try using this script for converting back to xml

%dw 2.0
output application/xml writeDeclaration=false
fun json2xml(data) = data mapObject (v, k, i) -> {
    ((k) @(
        (
            if(v is Object and !isEmpty(searchForAttr(v))) searchForAttr(v)
            else null
        )
    ): v match {
        case is Object -> if(namesOf(v) contains("__text")) searchForText(v) else json2xml(v)
        else -> v
    }) if (!(k contains "@") and !(k contains "__text"))
}
fun searchForAttr(v) = v mapObject {
    (($$[1 to -1]): $) if(($$ as String) startsWith("@")) 
}
fun searchForText(v) = v mapObject {
    (($$):$) if(($$ as String) == "__text")
} pluck $
---
json2xml(payload)

I tried it with a much more complex xml structure and it did convert back to the original xml, however the initial conversion to JSON (using the writeAttributes option) leaves out xml namespaces so if your original input has namespaces may need to go another route with the JSON conversion.

Upvotes: 2

Christian Chibana
Christian Chibana

Reputation: 568

JSON with Attributes to XML with Attributes:

%dw 2.0
output application/xml

fun collectAttributes(elem:Object) = 
    elem filterObject ((value, key, index) -> key contains  "@" )

fun putAttributes(elem: Object) =
    elem mapObject ((value, key, index) -> value match {
        case is Object -> do {
            var attr = collectAttributes(value)
            var withoutAttr = value -- attr
            ---
            (key) @((attr)): 
                if (keysOf(withoutAttr) contains "__text" as Key)
                    withoutAttr."__text" 
                else 
                    putAttributes(withoutAttr)
        }
        else -> (key): value
    })
        
---
putAttributes(payload)

I'm not sure if it is fully generalized to take every JSON with Attributes, but works in your case.

XML to JSON with Attributes: You could try the writer property writeAttributes.

%dw 2.0
output application/json writeAttributes=true
---
payload

https://docs.mulesoft.com/mule-runtime/4.3/dataweave-formats-json#properties

Upvotes: 2

Related Questions