Search code examples
xmlvb.net

Removing a node when an attribute exists


I have the following xml document.

<?xml version="1.0"?>
<report>
    <feature tag="Config"/>
    <feature tag="Runtime">
        <feature tag="Output">
            <feature tag="Target">
                    <property name="type" editable="false" visible="true" required="false" value="Html"/>
                    <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Html.Driver"/>
                </feature>
            <feature tag="Target">
                    <property name="type" editable="false" visible="true" required="false" value="Word"/>
                    <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Word.Driver"/>
                </feature>
            <feature tag="Target">
                    <property name="type" editable="false" visible="true" required="false" value="PDF"/>
                    <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Pdf.Driver"/>
                </feature>
            </feature>
        <feature tag="Log"/>
    </feature>
</report>

I want to read all three subnodes "Target" below the "Output" node in order to find out if the value="Html" is present.

If I find the value "Html", this subnode will be unremoved, all others below "Output" I want to remove, that below "Output" only exists one subnode of "Target".

I am using the XDocument class, but I have no success.

 Dim doc As New XmlDocument
        Dim nodes As XmlNodeList
        doc.Load(Path)

        nodes = doc.SelectNodes("/report/feature[@tag='Runtime']/feature[@tag='Output']/feature[@tag='Target']")

        For Each node As XmlNode In nodes
            If node.ChildNodes(0).Attributes("value").Value <> "Word" Then
                node.RemoveAll()
            End If
        Next


        doc.Save("c:\temp\test.xml")

The result below "Output" is the following, so the "Feature" tags are still remaining.

<feature tag="Output">
      <feature>
      </feature>
      <feature tag="Target">
        <property name="type" editable="false" visible="true" required="false" value="Word">
        </property>
        <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Word.Driver">
        </property>
        <property name="path" type="URI" editable="true" visible="true" required="true" value="">
        </property>
        
      </feature>
      <feature>
      </feature>
      <feature>
      </feature>
      <feature>
      </feature>
    </feature>


Solution

  • So here is the data I used

        Dim doc As XElement
        ' doc = XElement.Load("your path here")
    
        'for test use a literal
        doc = <report>
                  <feature tag="Config"/>
                  <feature tag="Runtime">
                      <feature tag="Output">
                          <feature tag="Target">
                              <property name="type" editable="false" visible="true" required="false" value="Html"/>
                              <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Html.Driver"/>
                          </feature>
                          <feature tag="Target">
                              <property name="type" editable="false" visible="true" required="false" value="Word"/>
                              <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Word.Driver"/>
                          </feature>
                          <feature tag="Target">
                              <property name="type" editable="false" visible="true" required="false" value="PDF"/>
                              <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Pdf.Driver"/>
                          </feature>
                      </feature>
                      <feature tag="Log"/>
                  </feature>
              </report>
    

    And the code

        Dim ie As IEnumerable(Of XElement)
        ie = From el In doc...<feature>
                Where el.@tag = "Output"
                 From sel In el...<property>
                  Where sel.@value = "Html"
                  Select sel.Parent
    
        If ie.Count = 1 Then
            Dim parent As XElement = ie(0).Parent
            Dim hld As XElement = New XElement(ie(0))
            ie(0).Parent.Nodes.Remove()
            parent.Add(hld)
        End If
    

    And the results

            'doc after above
            '<report>
            '  <feature tag="Config" />
            '  <feature tag="Runtime">
            '    <feature tag="Output">
            '      <feature tag="Target">
            '        <property name="type" editable="false" visible="true" required="false" value="Html" />
            '        <property name="driver" editable="false" visible="true" required="false" value="Telelogic.Html.Driver" />
            '      </feature>
            '    </feature>
            '    <feature tag="Log" />
            '  </feature>
            '</report>