Reputation: 783
I'm trying to read the version of an xml file:
<Order xsi:schemaLocation="urn:schemas-basda-org:2000:purchaseOrder:xdr:3.01 order-v3.xsd urn:schemas-bossfed-co-uk:OP-Order-v1 OP-Order-v1.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="urn:schemas-basda-org:2000:purchaseOrder:xdr:3.01">
<OrderHead>
<Schema>
<Version>3.05</Version>
</Schema>
<Parameters>
<Language>en-GB</Language>
<DecimalSeparator>.</DecimalSeparator>
<Precision>12.1</Precision>
</Parameters>
<OrderCurrency>
<Currency Code="GBP">GB Pounds</Currency>
</OrderCurrency>
</OrderHead>
The code I'm trying to use is:
Dim m_xmld As XmlDocument
Dim m_nodelist As XmlNodeList
Dim m_node As XmlNode
'Create the XML Document
m_xmld = New XmlDocument()
'Load the Xml file
m_xmld.Load(fileLocation)
'Show all data in your xml
MessageBox.Show(m_xmld.OuterXml)
'Get the list of name nodes
m_nodelist = m_xmld.SelectNodes("/Order/OrderHead/Schema")
For Each m_node In m_nodelist
GetXmlVersion = m_node.Attributes.GetNamedItem("Version").Value
Next
But, it doesent pull anything.
i changed it to:
Public Shared Function GetXmlVersion (ByVal fileLocation As String) As String
Dim m_xmld As XmlDocument = New XmlDocument()
m_xmld.Load (fileLocation)
GetXmlVersion = m_xmld.SelectSingleNode ("/Order/OrderHead/Schema/Version").InnerText
End Function
and i just get
NullReferenceException was Unhandled Object reference not set to an instance of an object.
because the m_xmld.selectsinglenode is null
Upvotes: 0
Views: 1663
Reputation: 43743
Your first problem is that you are trying to read the Version as an attribute instead of as a child element.
The second problem is that your XML document has a default namespace. That means that even though none of the elements explicitly specify a namespace prefix, they actually do belong to the urn:schemas-basda-org:2000:purchaseOrder:xdr:3.01
namespace. As you may be aware, the SelectSingleNode
method uses XPath to find the matching nodes. What you may not know, it that there is no way to force XPath to use a default namespace. As such, you need to specify the correct namespace for every node name that belongs to any namespace. To quote the relevant paragraph from the Official XPath Specification:
A QName in the node test is expanded into an expanded-name using the namespace declarations from the expression context. This is the same way expansion is done for element type names in start and end-tags except that the default namespace declared with xmlns is not used: if the QName does not have a prefix, then the namespace URI is null (this is the same way attribute names are expanded). It is an error if the QName has a prefix for which there is no namespace declaration in the expression context.
Therefore, you need to do something like this:
Public Shared Function GetXmlVersion(ByVal fileLocation As String) As String
Dim xmld As XmlDocument = New XmlDocument()
xmld.Load(fileLocation)
Dim manager As XmlNamespaceManager = New XmlNamespaceManager(xmld.NameTable)
manager.AddNamespace("n", xmld.DocumentElement.NamespaceURI)
Return xmld.SelectSingleNode("/n:Order/n:OrderHead/n:Schema/n:Version", manager).InnerText
End Function
In this example, xmld.DocumentElement.NamespaceURI
returns the default namespace URI for the root element (urn:schemas-basda-org:2000:purchaseOrder:xdr:3.01
). We assign it the prefix of "n", so then we need to put an "n:" prefix on every element name in the XPath.
Also, you'll note that I changed the GetXmlVersion =
line to Return
. Using the Return
keyword is the preferred method in VB.NET. Also, I changed the name of your m_xmld
variable to xmld
because it was confusing. Typically, when people prefix a variable name in VB with an m_
, that is to indicate that it is a private field of the class (a private variable declared at the class level, outside of any method). That is not the case here. xmld
is just a local method variable.
Upvotes: 2