Prevent JDOM2 from creating xmlns=“”

2019-09-18 15:05发布

问题:

I try to add new <class> elements to a persistence.xml file with JDOM2.

persistenceUnitEl.add(new Element("class").addContent(className));

The problem is that jdom2 always adds xmlns="" to the <class> elements.

How can i prevent this?

removeAttribute("xmlns") does not work and removeNameSpace(el.getNameSpace()) also does not work.

回答1:

JDOM only adds the xmlns="" if you add child elements to other elements that are already in a namespace. The default Namespace in XML is the one which has no prefix. In the following example:

<root>
    <child />
</root>

There are no namespace prefixes, and the default namespace is "".

The above XML snippet is semantically identical to:

<root xmlns="" >
    <child />
</root>

The xmlns="" means that, any time you see an element that has no prefix, that you should put it in the 'empty' namespace "".

Now, if you want to put things in a namespace, and have a prefix, you would do:

<ns:root xmlns:ns="http://mynamespace">
    <ns:child />
</ns:root>

Note that the root and child elements in the above example are in the namespace http://mynamespace, and that namespace has the prefix ns. The above code would be semantically identical to (has the same meaning as):

<root xmlns="http://mynamespace">
    <child />
</root>

In the above example, the default namespace is changed from "" to be http://mynamespace, so now elements that have no prefix are in that default namespace http://mynamespace. To reiterate, the following two documents are identical:

<ns:root xmlns:ns="http://mynamespace">
    <ns:child />
</ns:root>

and

<root xmlns="http://mynamespace">
    <child />
</root>

Now, what does all of this have to do with your problem?

Well, your element persistenceUnitEl must be in a default namespace that is not "". Somewhere on that element, or on of it's parents, you have something like:

<tagname xmlns="...something....">
    <PersistenceUnit>
    </PersistenceUnit>
</tagname>

In the above, the PersistenceUnit is in the namespace ...something..... Now, you are asking JDOM to add the element new Element("class") to the document, so you are getting:

<tagname xmlns="...something....">
    <PersistenceUnit>
        <class xmlns="" />
    </PersistenceUnit>
</tagname>

The reason is because you are telling JDOM to put it in the "" namespace (Namespace.NO_NAMESPACE). See the documentation for JDOM here: new Element(String name).

instead, what you want to do, is put it in the same namespace as the parent:

Namespace parentNamespace = persistenceUnitEl.getNamespace();
persistenceUnitEl.add(new Element("class", parentNamespace).addContent(className));

Now, the real question is whether the "class" element actually belongs in the same namespace as the parent, or not. But that is a question only you can answer.

Resources:

  • Namespace specification
  • Decent introduction
  • A tutorial (quite advanced)
  • JDOM's NamespaceAware documentation
  • JDOM's FAQ


回答2:

From my understanding, I think this is what you want.

<RootTagname xmlns="...some namespace....">
    <SubTag>
        <NewElement yourAttrib="1"/>
    </SubTag> 
</RootTagname >

This is what you get.

<RootTagname xmlns="...some namespace....">
    <SubTag>
        <NewElement xmlns="" yourAttrib="1"/>
    </SubTag> 
</RootTagname >

Use the below snippet to create the new Element

Element newElement = new Element("NewElement", subElement.getNamespace());

Here is the full code.

Namespace namespace = Namespace.getNamespace("prefix", ".....some namespace....");
XPathBuilder<Element> subTagXpathelementBuilder = new XPathBuilder<Element>("//prefix:SubTag", Filters.element());
subTagXpathelementBuilder.setNamespace(namespace);
XPathFactory xpathFactory = XPathFactory.instance();

Document doc = (Document) builder.build(xmlFile);

XPathExpression<Element> xpath = subTagXpathelementBuilder .compileWith(xpathFactory);
List<Element> subElementsList = xpath.evaluate(doc);
for (Element subElement : subElementsList ) {
    Element newElement = new Element("NewElement", subElement.getNamespace());

    List<Attribute> newElementAttribList = newElement.getAttributes();
    newElementAttribList .add(new Attribute("yourAttrib", "1"));
    subElement .addContent(newElement);
} 


标签: java jdom jdom-2