I\'d like to change the tag name of a MSXML XMLDOMElement, but unfortunately the nodeName property is read-only. Is there any straightforward way to do it, or have
Just for reference, I ended up with a replace function which is copying all children to a newly created node: (VB6 sample code)
Private Sub ReplaceNodeName(oDoc As DOMDocument, oElement As IXMLDOMElement, newName As String)
Dim ohElement As IXMLDOMElement
Dim sElement As IXMLDOMElement
Dim oChild As IXMLDOMNode
' search the children '
If Not oElement Is Nothing Then
Set ohElement = oElement.parentNode
Set sElement = oDoc.createElement(newName)
For Each oChild In oElement.childNodes
Call sElement.appendChild(oChild)
Next
Call ohElement.replaceChild(sElement, oElement)
End If
End Sub
This is "universal" rename node function (ObjectPascal) using MSXML interfaces, works fine and may be usable:
function RenameXMLTag(e: IXMLNode; NewName: WideString): IXMLNode;
var
Doc : IXMLDocument;
NewElem, NParent : IXMLNode;
DNOld, DNNew : IDOMNode;
AC : IXMLNodeList;
i: Integer;
begin
Doc := e.OwnerDocument;
NewElem := Doc.CreateNode(NewName, e.NodeType);
while e.HasChildNodes do
NewElem.DOMNode.AppendChild(e.DOMNode.firstChild);
AC := e.AttributeNodes;
for i := 0 to AC.Count - 1 do
NewElem.Attributes[AC[i].NodeName] := AC[i].NodeValue;
NParent := e.ParentNode;
DNOld := e.DOMNode;
DNNew := NewElem.DOMNode;
NParent.DOMNode.replaceChild(DNNew, DNOld);
Result := NewElem;
end;
This is my c++ version, maybe you will understand it easier:
#define SAFERELEASE(comobj) \
if (comobj) \
{ \
comobj->Release(); \
comobj = NULL; \
}
void RenameElement(IXMLDOMElement * pElement, LPWSTR newName)
{
if (NULL == pElement)
return;
IXMLDOMDocument * pParentDoc = NULL;
pElement->get_ownerDocument(&pParentDoc);
IXMLDOMElement * pNewElement = NULL;
pParentDoc->createElement(newName, &pNewElement);
VARIANT_BOOL bHasNodes;
pElement->hasChildNodes(&bHasNodes);
while (bHasNodes)
{
IXMLDOMNode * pFirstChild = NULL;
pElement->get_firstChild(&pFirstChild);
pNewElement->appendChild(pFirstChild, NULL);
pElement->hasChildNodes(&bHasNodes);
SAFERELEASE(pFirstChild);
}
IXMLDOMNamedNodeMap * pAttrMap = NULL;
IXMLDOMNamedNodeMap * pAttrMapNew = NULL;
pElement->get_attributes(&pAttrMap);
pNewElement->get_attributes(&pAttrMapNew);
long nAttrLength = 0;
pAttrMap->get_length(&nAttrLength);
for (int n = 0; n < nAttrLength; n++)
{
IXMLDOMNode * pListItem = NULL;
pAttrMap->get_item(n, &pListItem);
BSTR wsAttrName = NULL;
pListItem->get_nodeName(&wsAttrName);
BSTR wsAttrValue = NULL;
pListItem->get_text(&wsAttrValue);
IXMLDOMAttribute * pAttribute = NULL;
pParentDoc->createAttribute((BSTR)wsAttrName, &pAttribute);
pAttribute->put_value(CComVariant((BSTR)wsAttrValue));
pAttrMapNew->setNamedItem(pAttribute, NULL);
SAFERELEASE(pAttribute);
SysFreeString(wsAttrValue);
SysFreeString(wsAttrName);
SAFERELEASE(pListItem);
}
IXMLDOMNode * pParent = NULL;
pElement->get_parentNode(&pParent);
pParent->replaceChild(pNewElement, pElement, NULL);
SAFERELEASE(pAttrMapNew);
SAFERELEASE(pAttrMap);
SAFERELEASE(pParent);
SAFERELEASE(pNewElement);
SAFERELEASE(pParentDoc);
}
According to Document Object Model you can't rename a node.
See: http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247
renameNode is possible in DOM Level 3 but not in MSXML library