StealthRT StealthRT - 6 months ago 7
Vb.net Question

Parsing XML with class that are uniquely numbered

Hey all I have the following code that I am in need of finding the class in:

Dim nodelist As System.Xml.XmlNodeList = Nothing
Dim doc As New System.Xml.XmlDocument()

doc.LoadXml(tmpData)
nodelist = doc.SelectNodes("//entry/content/sp_0:div/span/sp_0:span")

For Each node As System.Xml.XmlElement In nodelist
Debug.print(node("OrderID").InnerText)
Next


And the XML looks like this:

<feed
xmlns:app="http://www.w3.org/2007/app"
xmlns:thr="http://purl.org/syndication/thread/1.0"
xmlns:fh="http://purl.org/syndication/history/1.0"
xmlns:snx="http://www.ibm.com/xmlns/prod/sn"
xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"
xmlns="http://www.w3.org/2005/Atom">
<id>2006:feed</id>
<generator version="5.0.0.0" uri="http://www.ibm.com/xmlns/prod/sn">IBM Connections - Profiles</generator>
<title type="text">reporting chain for Bill Gates</title>
<opensearch:itemsPerPage>8</opensearch:itemsPerPage>
<fh:complete></fh:complete>
<link
href="http://..."
rel="self"
type="application/atom+xml"></link>
<entry>
<id>tag:profiles.ibm.com,2006</id>
<title type="text">Bill Gates</title>
<updated>2016-05-11T06:39:54.908Z</updated>
<category term="profile" scheme="http://www.ibm.com/xmlns/prod/sn/type"></category>
<contributor>
<name>Bill Gates</name>
<snx:userid>010101</snx:userid>
<email>Bill_Gates@microsoft.com</email>
<snx:userState>active</snx:userState>
<snx:isExternal>false</snx:isExternal>
</contributor>
<link
href="http://..."
rel="http://www.ibm.com/xmlns/prod/sn/profile-type"
type="application/profile-type+xml"></link>
<thr:in-reply-to>
<app:accept>ref</app:accept>
<app:accept>tag:profiles.ibm.com,2006</app:accept>
</thr:in-reply-to>
<summary type="text">Profile information for Bill Gates</summary>
<content type="xhtml">
<sp_0:div
xmlns="http://www.w3.org/1999/xhtml"
xmlns:sp_0="http://www.w3.org/1999/xhtml">
<sp_0:span class="vcard">
<sp_0:div class="x-groupwareMail" style="display:none"></sp_0:div>
<sp_0:div class="org">
<sp_0:span class="organization-unit"></sp_0:span>
</sp_0:div>
<sp_0:div class="role"></sp_0:div>
<sp_0:div class="title">Applications Developer/Analyst</sp_0:div>
<sp_0:div class="uid">265418</sp_0:div>
<sp_0:div class="x-profile-uid">010101</sp_0:div>
<sp_0:div class="x-lconn-userid">265418</sp_0:div>
</sp_0:span>
</sp_0:div>
</content>
</entry>
<entry>
etc....
</entry>
</feed>


I get an error on nodelist = doc.SelectNodes("//entry/content/sp_0:div/span/sp_0:span") saying:


Namespace Manager or XsltContext needed. This query has a prefix, variable, or user-defined function.


How can I get the internal text 010101 from that class?

Answer

You will need to use the XmlNamespaceManager class to define the namespaces used in your XPath, and pass this to the SelectNodes method. In addition, I couldn't get an empty namespace to work for the default namespace (perhaps a limitation with XPath?), so had to define a prefix for that.

Also, your XPath doesn't seem to match your sample XML. Lets say you wanted to get the value for the <sp_0:div class="x-profile-uid">010101</sp_0:div> element, you would want something like this:

Dim nodelist As System.Xml.XmlNodeList = Nothing
Dim doc As New System.Xml.XmlDocument()

doc.LoadXml(tmpData)

Dim nsmgr = New XmlNamespaceManager(doc.NameTable)
nsmgr.AddNamespace("atom", "http://www.w3.org/2005/Atom")
nsmgr.AddNamespace("sp_0", "http://www.w3.org/1999/xhtml")

nodelist = doc.SelectNodes(
    "//atom:entry/atom:content/sp_0:div/sp_0:span/sp_0:div[@class='x-profile-uid']",
    nsmgr
)

For Each node As System.Xml.XmlElement In nodelist
   Debug.Print(node.InnerText)
Next

Which outputs:

010101

Hopefully you can adapt this to your needs.