0

I converted an XML snippet to JSON using the writeAttributes=true property.

XML:

<family surname="Simpsons">
  <father age="42">Homer</father>
  <mother age="41">Marge</mother>
  <children>
    <child age="9">Bart</child>
    <child age="8">Lisa</child>
    <child age="1">Maggie</child>
  </children>
</family>

DataWeave:

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

Resulting JSON:

{
  "family": {
    "@surname": "Simpsons",
    "father": {
      "@age": "42",
      "__text": "Homer"
    },
    "mother": {
      "@age": "41",
      "__text": "Marge"
    },
    "children": {
      "child": [
        {
          "@age": "9",
          "__text": "Bart"
        },
        {
          "@age": "8",
          "__text": "Lisa"
        },
        {
          "@age": "1",
          "__text": "Maggie"
        }
      ]
    }
  }
}

XML attributes and values are retained in the JSON through use of modified keys: "@key" for the attribute, and "__text" for the value. While the operation to go from XML to JSON is straightforward with the writeAttributes writer property, there doesn't seem to be an equivalent to do the reverse. Using this result format, I want to convert similar JSON to the original XML.

What's the simplest way to transform JSON back to XML and reintegrate the attributes?


Edit:

Using aled's transform here on the resulting JSON payload above, I was able to get a close result, but the child array elements didn't reacquire the age attribute.

aled's DataWeave:

%dw 2.0
output application/xml
fun getAttributes(x) =
   x match {
      case is Object -> x filterObject ($$ as String startsWith "@") 
         mapObject ((value, key, index) -> (key[1 to -1] ): value)
      else -> $
   }
fun convertToAttributes(x) =
   x match  {
      case is Object -> x filterObject !($$ as String startsWith "@")
         mapObject ($$) @((getAttributes($))): convertToAttributes($)
      case is Array -> x map convertToAttributes($)
      else -> $
   }
---
convertToAttributes(payload)

Resulting XML:

<?xml version='1.0' encoding='UTF-8'?>
<family surname="Simpsons">
  <father age="42">Homer</father>
  <mother age="41">Marge</mother>
  <children>
    <child>Bart</child>
    <child>Lisa</child>
    <child>Maggie</child>
  </children>
</family>

__text somehow becomes the value during the transform.

I'm not sure why it's not picking up the age in the array.

7
  • What specific data model conversions are you thinking of? What would happen with a simple JSON string? An array of strings? An array of mixed types? An object with three different keys? Commented Nov 3, 2024 at 21:37
  • @Ryan For a load data model, I would adhere to the same format that writeAttributes creates. Commented Nov 4, 2024 at 1:23
  • Aha I see! Right this would be a useful transform... I didn't get that from the question as written. Maybe you can clarify that you want a dataweave function to produce the original XML from the JSON you included. Commented Nov 7, 2024 at 15:54
  • @Ryan I do say that, explicitly in the question: "I want to convert similar JSON to the original XML." Commented Nov 7, 2024 at 20:23
  • Edit your question adding what you tried and the results and why it didn't work for you. Commented Nov 11, 2024 at 23:51

1 Answer 1

0

Try this:

%dw 2.0
output application/xml
---
{
    family @(surname: payload.family.'@surname'): {
        father @(age: payload.family.father.'@age'): 
payload.family.father.'__text',
        mother @(age: payload.family.mother.'@age'): 
payload.family.mother.'__text',
        children: {
            (payload.family.children.child map (child) -> {
                child @(age: child.'@age'): child.'__text'
            })
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Hi @Fredie, I'm looking for a generic dw transform. Hardcoded tags and attributes won't work because the inbound JSON will change, and it may include several @ attributes per tag. If you look at aled's dw, it's almost complete, but the array tags aren't picking up their attributes.
Thank you for contributing to the Stack Overflow community. This may be a correct answer, but it’d be really useful to provide additional explanation of your code so developers can understand your reasoning. This is especially useful for new developers who aren’t as familiar with the syntax or struggling to understand the concepts. Would you kindly edit your answer to include additional details for the benefit of the community?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.