ALQH
ALQH

Reputation: 161

Adding an element to the root element

I have an XML file that looks something like this (a maven pom.xml if anyone's familiar):

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    ...
</project>

I wanted to add add a <packaging> element so that it looks like this

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <packaging>pom</packaging>
</project>

So I did this:

doc = (Document)builder.build(modelToWriteTo);
rootProj = doc.getRootElement();
Element packagingTag = rootProj.getChild("packaging");
if(packagingTag != null) {
        packagingTag.setText(elementValue);         
} else {
    packagingTag = new Element("packaging").setText(elementValue);
    rootProj.addContent(packagingTag);  
}

so that if there's a child element called "packaging" then I just want to reset the value, if not then I want to add a new tag.

The problem is when I did that my <packaging> element came as:

<project>
    <packaging xmlns="">pom</packaging>
</project>

So I read somewhere it might be something to do with the namespace, so I changed my code to:

doc = (Document)builder.build(modelToWriteTo);
rootProj = doc.getRootElement();
Element packagingTag = rootProj.getChild("packaging");
if(packagingTag != null){
        packagingTag.setText(elementValue);         
} else {
    packagingTag = new Element("packaging").setText(elementValue);
    packagingTag.setNamespace(rootProj.getNamespace());
    rootProj.addContent(packagingTag);      
}

and it appears nicely without the xmlns attribute:

<project>
    <packaging>pom</packaging>
</project>

However, when another thread comes in to read it again, and find rootProj.getChild("packaging"), it returns null. thus, another attempt to modify the packaging tag lead to the thread thinking that it doesn't exist and adds a new tag resulting in:

<project>
    <packaging>pom</packaging>
    <packaging>pom</packaging>
    <packaging>pom</packaging>
</project>

with the previous code where I didn't set the namespace, it was able to retrieve rootProj.getChild("packaging").....

I must have miss something here but I can't see where. Please help!

Upvotes: 1

Views: 334

Answers (2)

Wayne
Wayne

Reputation: 60414

You're asking for the packaging element that's in no namespace, but no such node exists, because your packaging node is in the default namespace (xmlns="http://maven.apache.org/POM/4.0.0"). You need to specify this namespace when selecting the element:

Element packagingTag = rootProj.getChild("packaging", 
    Namespace.getNamespace("http://maven.apache.org/POM/4.0.0"));

Note: The reason it worked before is because this:

<packaging xmlns="">pom</packaging>

...contains a namespace "undeclaration" (xmlns="") that reverts the element to existing in no namespace.

Upvotes: 1

Dev
Dev

Reputation: 12196

You need to use the Element.getChild(String, Namespace) version of the method and pass the correct namespace (which in this case is http://maven.apache.org/POM/4.0.0).

Upvotes: 1

Related Questions