How to overwrite root element - java

I have a come to a scenario whereby I need to overwrite the root (w3c dom) Document element with a new element after it has been created elsewhere. So far I have tried two different ways of achieving this:
document.removeChild(document.getDocumentElement());
AND subsequently this:
newElement = document.getDocumentElement();
newElement = document.createElement("newRootElementName");
document.appendChild(newElement);
Neither seem to overwrite the root element, and, after saving, the document seems only to contain the root element that is empty.

Going with the example I found here, here's how you could do it. Since there's apparently no method to change the name of an element, you would have to do the following:
Create another element with the new name
Copy the old element's attributes
Copy the old element's children
And finally replace the node.
For example:
// Obtain the root element
Element element = document.getDocumentElement();
// Create an element with the new name
Element element2 = document.createElement("newRootElementName");
// Copy the attributes to the new element
NamedNodeMap attrs = element.getAttributes();
for (int i=0; i<attrs.getLength(); i++) {
Attr attr2 = (Attr)document.importNode(attrs.item(i), true);
element2.getAttributes().setNamedItem(attr2);
}
// Move all the children
while (element.hasChildNodes()) {
element2.appendChild(element.getFirstChild());
}
// Replace the old node with the new node
element.getParentNode().replaceChild(element2, element);

Related

Transform linkedhashmap into org.w3c.dom.Element

I need to create a method that given any LinkedHashMap , this method have to transform it into XML/Dom elements of a Document like :
#Override
public Element marshal(Object linkedHashMap) {
Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
final Element element = doc.createElement("root");
//For each attribute and object of the linked hashmap
// I must iterate recursively in order to get all the objects and atributes of the LinkedHashMap and append them to the root node element:
//element.appendChild(...));
return element; // here the element must be already populated with all the attributes of the linked hashmap and its values.
}
I have no idea about how can I achieve this , how can I loop through the attributes of a LinkedHashMap in order to map them to Element ?
I need something like this , but it must iterate over all the levels and sublevels (nested linkedhashmap objects) of the linkedhashmap:
private void marshalMapElements(ArrayList<LinkedHashMap> linkedHashMaps) {
Document doc = getDocument();
Element root = doc.createElement("root");
for (Map<String, Object> element : linkedHashMaps) {
Element e = doc.createElement(element.getKey());
e.setTextContent(element.getValue());
root.appendChild(e);
}
}
}

can't delete conditionally from xml using Java

I've an xml file that I need to delete certain elements depending on the attribute value. the unconditional deletion works just fine but this won't:
NodeList nodes = doc.getElementsByTagName("host");
Element d;
for ( int i = 0; i < nodes.getLength(); i++ ) {
String state = nodes.item(i).getChildNodes().item(0).getAttributes().item(0).getTextContent();
if("down".equals(state)){
d= (Element) nodes.item(0);
d.getParentNode().removeChild(d);
System.out.println(state);
}
}
There are a couple of problems with the code. The first is the line
String state = nodes.item(i).getChildNodes().item(0).getAttributes().item(0).getTextContent();
which assumes that 1) there are no text nodes between child elements, and 2) that the attribute looked for is always the first attribute in the list. This makes the code brittle and subject to failure if the format of the input document change.
The second problem is that while iterating over the node list, some of the members of the list are removed from their parent. The behavior of the list if detaching/removing children from their parent is not specified in the DOM API, why the effect could vary between implementations. Not sure if this is the case here, but I wouldn't depend on guessing.
I would suggest using XPath instead (much clearer and shorter). Something like this:
XPath xp = XPathFactory.newInstance().newXPath();
NodeList list = (NodeList) xp.evaluate("//node[*[#* = 'down']]", doc, XPathConstants.NODESET);
for(int i=0; i < list.getLength(); ++i) {
Node node = list.item(i);
node.getParentNode().removeChild(node);
}
The expression //node[*[#* = 'down']] selects all <node> elements that have a child element that has any attribute with value down.

How do I get all UI elements of a Webdyn Pro Java view?

Is there any way to recursively iterate over all elements inside the root element of a Webdyn Pro Java view?
For each found child element I would like to read/modify properties at runtime.
To iterate child elements of root element you should access root in wdDoModifyView() method:
IWDUIElementContainer root = (IWDUIElementContainer) view.getRootElement();
IWDUIElement[] elements = root.getChildren();
for (int i = 0; i < elements.length; i++) {
IWDUIElement element = elements[i];
String id = element.getId();
if (id.equals("Button")) {
IWDButton button = (IWDButton)view.getElement(id);
button.setText("someText");
}
}

org.w3c.dom.Element get position in parent

How to get the position of an Element in the childNode list?
e.g.
<a>
<b></b><!-- return 0 -->
<c></c><!-- return 1 -->
</a>
I don't think Element, Node, or NodeList provide a direct way to get this info, but it's easy enough to write your own quick function to do it:
int indexOfNode(Node node) {
int index;
Node sibling;
index = 0;
while ((sibling = node.getPreviousSibling()) != null) {
node = sibling;
++index;
}
return index;
}
I don't think there's a straightforward way other than to repeatedly call getPreviousSibling() until it returns null or iterate through the parent node's child list until you find one that is == to the node you started with.
As an aside, in the document you give in the question the b element is index 1 in its parent's list of children, and the c element is index 3, because there are whitespace-only text nodes in between (one between the opening a and opening b and another between the closing b and opening c).

Java DOM parsing fails to read node

I am trying to values of specific Nodes from an xml file, this is working fine.
However, there is one line i can't read which is :
<misc viewers="898" duration="6684"/>
I can find the node, but getNodeValue() and getTextContext() both return null.
Is there a workaround to get the contents of this line?
Thanks
edit : i am using this loop to find nodes
NodeList nodes = doc.getElementsByTagName("item");
for (int i = 0; i < nodes.getLength(); i++) {
Element element = (Element) nodes.item(i);
System.out.println("Title: "
+ getElementValue(element, "title"));
System.out
.println("embed: " + getElementValue(element, "misc"));
System.out.println();
}
viewers and duration are attributes of the misc node, not values. You need to call getAttributes() to get a NamedNodeMap of all the attributes, then call getNamedItem() on your node map to access a specific attribute.

Categories