2009-10-13 11 views
2

Je souhaite modifier le nom de balise d'un MSXML XMLDOMElement, mais malheureusement, la propriété nodeName est en lecture seule. Y a-t-il un moyen simple de le faire, ou dois-je travailler en faisant des insertion/remplacement et des copies en profondeur des enfants?Modifier le NodeName d'un élément de balise XML à l'aide de MSXML

<xml> ... 
    <oldTagName> 
     ... sub-elements 
    </oldTagName> 
<more xml> ... 

devrait devenir

<xml> ... 
    <newTagName> 
     ... sub-elements 
    </newTagName> 
<more xml> ... 

Répondre

1

Juste pour référence, je me suis retrouvé avec une fonction de remplacement qui copie tous les enfants à un nœud nouvellement créé: (VB6 code exemple)

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 
2

Ceci est fonction de noeud renommer "universel" (ObjectPascal) en utilisant des interfaces MSXML, fonctionne très bien et peut être utilisable:

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; 
1

Ceci est mon C++ version, peut-être vous comprendrez plus facilement:

#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); 
} 
+0

: S'il vous plaît être plus descriptif dans votre réponse. Reportez-vous à: [Comment répondre] (http://stackoverflow.com/questions/how-to-answer) – askmish