Search code examples
asp.netxmlvb.netxml-namespacesxmldocument

Not reading XML elements with namespace


I've got the following XML document information:

<Document xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:hl7-org:v3 CDA_SDTC.xsd" xmlns="urn:hl7-org:v3" xmlns:cda="urn:hl7-org:v3" xmlns:sdtc="urn:hl7-org:sdtc">
  <component>
    <structuredBody>
      <component>
        <section>
          <templateId root="2.16.840.1.113883.10.20.22.2.45" />
          <title>Instructions</title>
          <text>
            <paragraph>Putting instructions into the node to read out into the text area.</paragraph>
          </text>
        </section>
      </component>
    </structuredBody>
  </component>
</Document>

I have to have the XML document loaded by a VB.NET page in order to look for this particular information and put the contents of the paragraph node into a text area form field on a web page. This was working with no problem, but the document root had some namespace information added and now it's not working. This is the VB.NET code:

m_nodelist = m_xmld.SelectNodes("Document/component/structuredBody/component/section")
For Each m_node In m_nodelist
  If m_node("title").InnerText = "Instructions" Then
    Dim Instructions As String = m_xmld.SelectSingleNode("Document/component/structuredBody/component/section[title='Instructions']/text/paragraph").InnerText
    txtInstructions.Text = Replace(patientInstructions, "<br>", Chr(10) & Chr(13))
    hfInstructionsOld.Value = Replace(patientInstructions, "<br>", Chr(10) & Chr(13))
  End If
Next

I presume it was working before because the root node didn't have a namespace defined. Now that it does. I don't know how to change the VB.NET code to account for that.


Solution

  • Since a default namespace is now defined on the root element, all of the elements belong to that namespace, by default. When using XPath (as you are doing with SelectNodes and SelectSingleNodes), you must always explicitly specify the namespace. There is no way, with XPath, to specify a default namespace which is always used when no namespace is explicitly specified. Here's how to do it:

    Dim nsmgr As New XmlNamespaceManager(m_xmld.NameTable)
    nsmgr.AddNamespace("x", "urn:hl7-org:v3")
    m_nodelist = m_xmld.SelectNodes("x:Document/x:component/x:structuredBody/x:component/x:section", nsmgr)
    For Each m_node In m_nodelist
        If m_node("title").InnerText = "Instructions" Then
            Dim Instructions As String = m_xmld.SelectSingleNode("x:Document/x:component/x:structuredBody/x:component/x:section[x:title='Instructions']/x:text/x:paragraph", nsmgr).InnerText
            txtInstructions.Text = Replace(patientInstructions, "<br>", Chr(10) & Chr(13))
            hfInstructionsOld.Value = Replace(patientInstructions, "<br>", Chr(10) & Chr(13))
        End If
    Next
    

    Or, if you want it to just dynamically get the namespace from the root element, you can do this:

    nsmgr.AddNamespace("x", m_xmld.DocumentElement.NamespaceURI)