currarpickt
currarpickt

Reputation: 2302

Delete several nodes in XML File using NSIS

I want to compare two files: one is xml file and the other is text file. If there is a string that appears in the xml file but not in the text file, it will be deleted from xml file.

I tried using xml.nsh and also function FileSearch to compare them. After I remove one node, the looping always stop because it cannot find the nextsibling. Any idea how to continue the loop?

${xml::LoadFile} "$TEMP\$IISXMLFile" $0
${xml::GotoPath} "/unattend/servicing/package" $0
${xml::FirstChild} "assemblyIdentity" $1 $0
${xml::NextSibling} "selection" $7 $0
${While} $0 == 0 
      ${xml::GetAttribute} "name" $3 $4
      Push $TEMP\featurelist.txt
      Push $3
      Call FileSearch
      Pop $0 #Number of times found throughout
      Pop $1 #Number of lines found on

      ${IF} $0 == 0
           ${xml::RemoveNode} $7
      ${ENDIF}

      ${xml::NextSibling} "selection" $7 $0
${EndWhile}      
${xml::SaveFile} "$TEMP\$IISXMLFile" $0    
${xml::NodeHandle} $0
${xml::Unload}

I solved it using this code:

${xml::LoadFile} "$TEMP\$IISXMLFile" $0    
loopXML:
   ${xml::GotoPath} "/unattend/servicing/package" $0
   ${xml::FirstChild} "assemblyIdentity" $1 $0
   ${xml::NextSibling} "selection" $7 $0
   ${While} $0 == 0 
        ${xml::GetAttribute} "name" $3 $4
        Push $TEMP\featurelist.txt
        Push $3
         Call FileSearch
        Pop $0 #Number of times found throughout
        Pop $1 #Number of lines found on

        ${IF} $0 == 0
             ${xml::RemoveNode} $7    
             ${xml::NodeHandle} $0
             goto loopXML
        ${ENDIF}
        ${xml::NextSibling} "selection" $7 $0
   ${EndWhile}      
${xml::SaveFile} "$TEMP\$IISXMLFile" $0    
${xml::NodeHandle} $0
${xml::Unload}

Upvotes: 1

Views: 296

Answers (1)

Anders
Anders

Reputation: 101606

I'm guessing this happens because the current node is stored internally somewhere and when you delete it you end up in the parent node. There are probably two ways you can solve this.

  • Call ${xml::NodeHandle} to save the current node handle, call ${xml::NextSibling} and save that node as well. You can then use ${xml::GotoHandle} to delete and then go to the next node...

  • Restart the loop from the beginning every time you remove a node...

Upvotes: 1

Related Questions