1

I have an dynamic XML that needs to be transformed based on the values of its XML. The group nodes with an attribute type="newNode" needs to be removed because they are already derived.

I tried the following:

  1. Create new nodes based on the XML and delete the unnecessary nodes but I encountered an issue when using doc.removeChild(node) saying

    Exception in thread "main" org.w3c.dom.DOMException: NOT_FOUND_ERR: An attempt is made to reference a node in a context where it does not exist.

    NodeList nodeList = doc.getElementsByTagName(NODE_MAPPINGS_NODE);
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node nodeToBeRemoved = nodeList.item(i);
        if (nodeToBeRemoved.getNodeType() == Node.ELEMENT_NODE) {
            doc.getDocumentElement().removeChild(nodeToBeRemoved);
        }
    }
    
  2. Created a new document based on the original document but I encountered an error saying

    Exception in thread "main" org.w3c.dom.DOMException: HIERARCHY_REQUEST_ERR: An attempt was made to insert a node where it is not permitted.

    NodeList nodeList = doc.getElementsByTagName(NODE_MAPPINGS_NODE);
    for (int i = 0; i < nodeList.getLength(); i++) {
        Node node = nodeList.item(i);
        if (node.getNodeType() == Node.ELEMENT_NODE) {
            if(!node.hasAttributes()) {
                Element elem = newDoc.createElement(node.getNodeName());
                newDoc.appendChild(elem);
            }
        }
    }
    

Here is the sample XML that I am trying to parse:

<root>
    <input>
        <nodeMappings type="newNode">
            <name>declarationType</name>
            <type>derived</type>
            <derivedValue>X</derivedValue>
        </nodeMappings>
        <nodeMappings type="newNode">
            <name>identificationNumber</name>
            <type>derived</type>
            <derivedValue>5000000612</derivedValue>
        </nodeMappings>
        <characteristicsOfTaxPayer>
            <nodeMappings type="newNode">
                <name>collectivePerson</name>
                <type>derived</type>
                <derivedValue>X</derivedValue>
            </nodeMappings>
        </characteristicsOfTaxPayer>
        <listTest>
            <nodeMappings type="newNode">
                <name>primaryKey</name>
                <type>derived</type>
                <derivedValue>1</derivedValue>
            </nodeMappings>
            <nodeMappings type="newNode">
                <name>value</name>
                <type>derived</type>
                <derivedValue>test1</derivedValue>
            </nodeMappings>
        </listTest>
        <listTest>
            <nodeMappings type="newNode">
                <name>primaryKey</name>
                <type>derived</type>
                <derivedValue>2</derivedValue>
            </nodeMappings>
            <nodeMappings type="newNode">
                <name>value</name>
                <type>derived</type>
                <derivedValue>test2</derivedValue>
            </nodeMappings>
        </listTest>
    </input>
</root>

After processing it should look like this:

<root>
    <input>
        <declarationType>X</declarationType>
        <identificationNumber>5000000612</identificationNumber>
        <characteristicsOfTaxPayer>
            <collectivePerson>X</collectivePerson>
        </characteristicsOfTaxPayer>
        <listTest>
            <primaryKey>1</primaryKey>
            <primaryKey>test1</primaryKey>
        </listTest>
        <listTest>
            <primaryKey>2</primaryKey>
            <primaryKey>test2</primaryKey>
        </listTest>
    </input>
</root>

Is there a better way to do this?

Cronas De Se
  • 331
  • 4
  • 21
  • There seems to be one inconsistency or I'm mistaken. But al new elements are created based on there name-element apart from value. This becomes primaryKey. Is that correct? – Siebe Jongebloed May 13 '21 at 13:35

1 Answers1

0

The complete job could be done with a simple xslt.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  
  <xsl:output method="xml" encoding="utf-8" indent="yes"/>
  
  <!-- Identity template : copy all text nodes, elements and attributes -->   
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="nodeMappings[@type='newNode']" >
    <xsl:element name="{name/text()}"><xsl:value-of select="derivedValue/text()"/></xsl:element>
  </xsl:template>

</xsl:stylesheet>

If it's correct that there is one exception in convention: that the text-value name-element becomes the new created element, that is <name>value</name> becomes <primaryKey/> the xslt would be:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  
  <xsl:output method="xml" encoding="utf-8" indent="yes"/>
  
  <!-- Identity template : copy all text nodes, elements and attributes -->   
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()" />
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="nodeMappings[@type='newNode']" >
    <xsl:element name="{name/text()}"><xsl:value-of select="derivedValue/text()"/></xsl:element>
  </xsl:template>

  <xsl:template match="nodeMappings[@type='newNode'][name='value']" >
    <primaryKey><xsl:value-of select="derivedValue/text()"/></primaryKey>
  </xsl:template>

</xsl:stylesheet>
Siebe Jongebloed
  • 3,906
  • 2
  • 14
  • 19
  • Did this answered your question? – Siebe Jongebloed May 14 '21 at 23:20
  • I am currently trying to research regarding XSLT because I have never tried it before and I am not sure if I can implement it in my code because we are using a framework created by our company. – Cronas De Se May 15 '21 at 11:43
  • If you choose to use xsl (No better language if you want to transform xml), I advise you to look at saxon-he. For implementation in Java, see i.e. https://stackoverflow.com/questions/40181386/how-to-run-saxon-xslt-transformation-in-java – Siebe Jongebloed May 15 '21 at 11:56