Skip to main content
ChuckE
Gold ⭐️
July 29, 2022
Solved

Preserving the parent element in XML document with XMLReader

When using the XMLReader service, how do you retain the outermost parent element of an XML document so when I convert it to JSON I have the outermost element in the JSON version too?

 

For example, given the following XML document how do I capture the "<a>" element rather than just the "<b>" element?  

 

<a>
<b>45</b>
</a>

 

What I want:

{"a": {"b":45}}

 

What I get:

{"b":45}

 

ChuckE
ChuckEAnswer
Gold ⭐️
August 3, 2022

I've since discovered a super easy way to resolve this.  Simply using the XMLRecordSetWriter does EXACTLY what I was looking for.  

11 replies

SAMSAL
Platinum ⭐️⭐️⭐️
July 29, 2022

Hi,

Im not sure this can be fixed by changing some configuration on what you have wither on the processor or the service level. Since the root element is not considered in the conversion from xml to Json, as workaround you can surround your xml with arbitrary root element with the ReplaceText Processor before the ConvertRecrod Processor:

SAMSAL_0-1659116224899.png

  •   Search Value: (?s)(^.*$)
  •   Replacement Value: <root>$1</root>
  •   Evaluation Mode: Entire Text

 This will output the following xml:

<root>n<a>
<b>45</b>
</a>
n</root>

And After ConvertRecord Prceossor :

{"a": {"b":45}}

Hope that helps. If it does, please Accept Solution.

Thanks

 

 

 

 

 

 

 

Translate
ChuckE
ChuckEAuthor
Gold ⭐️
August 1, 2022

Thank you SAMSL for your response.  In the interest of scalability I was trying to avoid performing text manipulations.  I ultimately decided to go with an XSLT transform since this processor is optimized for performing these types of operations, making it more scalable.  I wanted to verify there wasn't an option within the XMLReader that I was missing, but it seems not.  

On a side note, as an intellectual curiosity I also tried using the QueryRecord processor to see if I could select the outermost element in a query and slap wrapper text around it.  But it seems there is no way to perform this task with an XMLReader because it can't discern the schema of the data, so "select * from flowfile" is the only thing that works apparently.  

Translate
araujo
Platinum ⭐️⭐️⭐️
Platinum ⭐️⭐️⭐️
August 1, 2022

@ChuckE 

 

Do your XML messages conform to defined a schema?

 

Cheers,

André

Translate
-- Was your question answered? Please take some time to click on "Accept as Solution" below this post. If you find a reply useful, say thanks by clicking on the thumbs up button.
araujo
Platinum ⭐️⭐️⭐️
Platinum ⭐️⭐️⭐️
August 3, 2022

@ChuckE ,

 

You can use a JoltTransformRecord processor to perform the conversion to JSON and, at the same time, add the root node back to it.

 

araujo_0-1659503928628.png

The JOLT specification I used is this:

{
"*": "a.&"
}

 

Cheers,

André

 

 

Translate
-- Was your question answered? Please take some time to click on "Accept as Solution" below this post. If you find a reply useful, say thanks by clicking on the thumbs up button.
ChuckE
ChuckEAuthor
Gold ⭐️
August 3, 2022

This seems like a good idea.  I'll give this a try and test the performance against the XSLT transform.  I've never used the JOLT processors before so this will be a good opportunity to experiment with one.  Thanks for the idea.

Translate
araujo
Platinum ⭐️⭐️⭐️
Platinum ⭐️⭐️⭐️
August 3, 2022

I'm also curious about the performance difference. If you could report your results here, I'd appreciate!

 

Cheers,

André

 

Translate
-- Was your question answered? Please take some time to click on "Accept as Solution" below this post. If you find a reply useful, say thanks by clicking on the thumbs up button.
ChuckE
ChuckEAuthorAnswer
Gold ⭐️
August 3, 2022

I've since discovered a super easy way to resolve this.  Simply using the XMLRecordSetWriter does EXACTLY what I was looking for.  

Translate
SAMSAL
Platinum ⭐️⭐️⭐️
August 4, 2022

Can you explain how did you resolve it with XMLRecrodSetWriter? Thanks

Translate
ChuckE
ChuckEAuthor
Gold ⭐️
August 4, 2022

I create an XMLRecordSetWriter in the Controller Services, then using a ConvertRecord processor I'm able to read the xml record and then immediately write it out with a new root tag, which I can then pass to my next processor.  I discovered this when I was reading the documentation for the XMLRecordSetWriter.  Very first line in the documentation. 😃

https://nifi.apache.org/docs/nifi-docs/components/org.apache.nifi/nifi-record-serialization-services-nar/1.7.0/org.apache.nifi.xml.XMLRecordSetWriter/index.html

 

Translate