none
How to remove an Element/node from XmlDocument ?

    Question

  •  

    Hi!

    I want to remove the <ProductionExtract> and </Productionextract> tag from my xml below, how can i do this?

     

    <ProductionExtract>

    <Region Region="North">

    <MonthToDate>

    <ProductionSteel>0</ProductionSteel>

    </MonthToDate>

    <YearToDate>

    <ProductionSteel>0</ProductionSteel>

    </YearToDate>

    </Region>

    </ProductionExtract>

     

    I try to do the following in VB.NET, but that removed the whole of my XML!

     

    Dim xmlString As String = ProductionExtractDS.GetXml()

    Dim xmlDoc As New XmlDocument()

     

    xmlDoc.LoadXml(xmlString)

     

    Dim node As XmlNode = xmlDoc.SelectSingleNode("ProductionExtract")

    node.ParentNode.RemoveChild(node)

     

    So, is there a way to do this?

    Wednesday, July 09, 2008 11:22 AM

Answers

  • Well first of all you don't remove tags, you remove elements or attributes or comments or text nodes.

    As for removing the ProductionExtract element but keeping its contents, that is easily possible in your sample above as the element has just one child element, the one Region element. But what do you want to do if there are several child elements? In that case it is not clear what would become the new root element.

    Anyway, if you want to remove the ProductionExtract element and make its first child element, the Region element, the new root element, then you can achieve that with the DOM as follows:

    Code Snippet

    Dim doc As XmlDocument = New XmlDocument()

    doc.Load("..\..\XMLFile1.xml")

    doc.ReplaceChild(doc.DocumentElement.SelectSingleNode("Region"), doc.DocumentElement)

    doc.Save(Console.Out)

     

    You could also consider an XSLT stylesheet as follows:

    Code Snippet

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="@* | node()">

    <xsl:copy>

    <xsl:apply-templates select="@* | node()"/>

    </xsl:copy>

    </xsl:template>

    <xsl:template match="/ProductionExtract">

    <xsl:apply-templates/>

    </xsl:template>

    </xsl:stylesheet>

     

     

    Such a transformation could be executed with System.Xml.Xsl.XslCompiledTransform.
    Wednesday, July 09, 2008 11:53 AM
  • If you use .NET 2.0 or later and have a System.Xml.XmlDocument then you can use the Validate method http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.validate.aspx 

    so you would add schemas to the Schemas property and then call the Validate method, passing in your ValidationEventHandler that will then be called to report any validation errors:

    Code Snippet

    Dim doc As New XmlDocument()

    ' create and insert nodes here, then

    doc.Schemas.Add(Nothing, "schema1.xsd")

    ' add further schemas if needed here, then

    doc.Validate(yourValidationEventHandler)

     

     

    If you have an XML file then you don't need an System.Xml.XmlDocument, you can simply use an XmlReader with proper XmlReaderSettings to perform the validation.

    Thursday, July 10, 2008 1:07 PM
  • Well the error you get is a well-formedness error that is found earlier when you do the LoadXml(). The Validate method finds only validation errors, once you have an XmlDocument set up.

    So somehow your string concatenation is not producing well-formed XML.

    Thursday, July 10, 2008 2:22 PM

All replies

  • Well first of all you don't remove tags, you remove elements or attributes or comments or text nodes.

    As for removing the ProductionExtract element but keeping its contents, that is easily possible in your sample above as the element has just one child element, the one Region element. But what do you want to do if there are several child elements? In that case it is not clear what would become the new root element.

    Anyway, if you want to remove the ProductionExtract element and make its first child element, the Region element, the new root element, then you can achieve that with the DOM as follows:

    Code Snippet

    Dim doc As XmlDocument = New XmlDocument()

    doc.Load("..\..\XMLFile1.xml")

    doc.ReplaceChild(doc.DocumentElement.SelectSingleNode("Region"), doc.DocumentElement)

    doc.Save(Console.Out)

     

    You could also consider an XSLT stylesheet as follows:

    Code Snippet

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:template match="@* | node()">

    <xsl:copy>

    <xsl:apply-templates select="@* | node()"/>

    </xsl:copy>

    </xsl:template>

    <xsl:template match="/ProductionExtract">

    <xsl:apply-templates/>

    </xsl:template>

    </xsl:stylesheet>

     

     

    Such a transformation could be executed with System.Xml.Xsl.XslCompiledTransform.
    Wednesday, July 09, 2008 11:53 AM
  • Thanx

    That worked like a charm! (using DOM)

     

    As I do more and more regions my xml now looks like this:

     

    <Region Region="North">

    <MonthToDate>

    <ProductionSteel>0</ProductionSteel>

    </MonthToDate>

    <YearToDate>

    <ProductionSteel>0</ProductionSteel>

    </YearToDate>

    </Region>

    <Region Region="South">

    <MonthToDate>

    <ProductionSteel>0</ProductionSteel>

    </MonthToDate>

    <YearToDate>

    <ProductionSteel>0</ProductionSteel>

    </YearToDate>

    </Region>

     

    This is the code for creating that (looping for each region) - as you can see the DsToXmlString stringbuilder gets filled with each region:

     

    Dim xmlString As String = ProductionExtractDS.GetXml()

    Dim xmlDoc As New XmlDocument()

    xmlDoc.LoadXml(xmlString)

    xmlDoc.ReplaceChild(xmlDoc.DocumentElement.SelectSingleNode("Region"), xmlDoc.DocumentElement)

     

    Dim stringWriter As New System.IO.StringWriter

    Dim xmlWriter As New XmlTextWriter(stringWriter)

    xmlWriter.Formatting = Formatting.Indented

    xmlDoc.WriteTo(xmlWriter)

    DsToXmlString.Append(stringWriter.ToString())

     

    What I want to do now is to add the <ProductionExtract> element around the whole of this - causing the xml to look like this:

     

    <ProductionExtract>

    <Region Region="North">

    <MonthToDate>

    <ProductionSteel>0</ProductionSteel>

    </MonthToDate>

    <YearToDate>

    <ProductionSteel>0</ProductionSteel>

    </YearToDate>

    </Region>

    <Region Region="South">

    <MonthToDate>

    <ProductionSteel>0</ProductionSteel>

    </MonthToDate>

    <YearToDate>

    <ProductionSteel>0</ProductionSteel>

    </YearToDate>

    </Region>

    <ProductionExtract>

     

    Is there an easy way to add inn this element and to make it indent to do this ?

     

    Thanx in advance!

     

     

     

     

     

    Thursday, July 10, 2008 6:52 AM
  • I would not use strings and/or StringWriters or StringBuilders to construct XML as the .NET framework has better APIs to construct XML, there is XmlWriter and there is XmlDocument, that should suffice and makes sure the result is well-formed, something that string concatenation or StringWriter/Builder use does not ensure.

    Thus if you want to construct the XML you posted then you could easily construct it all using XmlWriter or XmlDocument.

    Thursday, July 10, 2008 12:40 PM
  • I've used XMLDocument for most part of my xml - but for adding this top level thingy I've used stringbuilders as a quick solution - although using XmlWriter probably is what I should have done.

    Thanx for the help so far!

     

    I have my complete constructed XML now and it's well formed and validates against my XSD when I use XMLSpy.

     

    What i now want to do is validate the xml against the schema within my VB code. Do you have a good tip on how to do that - lets try to keep it as simple as possible.. Smile

     

    Thursday, July 10, 2008 12:47 PM
  • If you use .NET 2.0 or later and have a System.Xml.XmlDocument then you can use the Validate method http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.validate.aspx 

    so you would add schemas to the Schemas property and then call the Validate method, passing in your ValidationEventHandler that will then be called to report any validation errors:

    Code Snippet

    Dim doc As New XmlDocument()

    ' create and insert nodes here, then

    doc.Schemas.Add(Nothing, "schema1.xsd")

    ' add further schemas if needed here, then

    doc.Validate(yourValidationEventHandler)

     

     

    If you have an XML file then you don't need an System.Xml.XmlDocument, you can simply use an XmlReader with proper XmlReaderSettings to perform the validation.

    Thursday, July 10, 2008 1:07 PM
  •  

    Thanx again! Smile

     

    So this is my code, but I never get to the handler even though I have error which i manually put into the xml:

    This is the code I use:

     

    Public Sub ValidateXmlAgainstSchema(ByVal XmlString As String)

    Dim xmlDocToValidate As New XmlDocument

    Dim test As New XmlExtracts

     

    xmlDocToValidate.LoadXml(DsToXmlString.ToString)

    xmlDocToValidate.Schemas.Add("", "C:\ProductionDataExtract.XSD")

     

    Dim eventHandler As ValidationEventHandler = New ValidationEventHandler(AddressOf test.ValidationEventHandler)

    xmlDocToValidate.Validate(eventHandler)

    End Sub

     

    Public Sub ValidationEventHandler(ByVal sender As Object, ByVal e As ValidationEventArgs)

    Select Case e.Severity

    Case XmlSeverityType.Error

    Debug.WriteLine("Error: {0}", e.Message)

    Case XmlSeverityType.Warning

    Debug.WriteLine("Warning {0}", e.Message)

    End Select

    End Sub

     

    But I put breakpoint inside ValidationEventHandler - but doesnt get there - just bumps out saying

    "ProductionDataExtract' start tag on line 1 does not match the end tag of 'ProductionDataExtractERRORTEST'" in the output window.

     

    So...any tip of what im doing wrong?

     

    Thursday, July 10, 2008 1:59 PM
  • Well the error you get is a well-formedness error that is found earlier when you do the LoadXml(). The Validate method finds only validation errors, once you have an XmlDocument set up.

    So somehow your string concatenation is not producing well-formed XML.

    Thursday, July 10, 2008 2:22 PM
  • Thanx!

     

    Ok, got fixed now well formed.

    Also validation now works with hardcoded path to XSD - trying to embedd the xsd but have some problems using it.

    Will create seperate thread for that issue.

     

    Friday, July 11, 2008 11:21 AM