Question

I'm using Vb.net and I need to get the Max Value of Visits from the following XML.

<Pages>
<Page posted="2006-03-27" visits="148" title="Don't Sweep That Under the Rug!"/>
<Page posted="2006-07-12" visits="191" title="Tire Swings for Grownups"/>
<Page posted="2006-11-07" visits="214" title="Eliminate Hornets from Your Picnic"/>
<Page posted="2006-06-14" visits="296" title="Why Ants Invade Your Kitchen"/>
<Page posted="2006-01-15" visits="227" title="101 Ways to Climb a Tree"/>
<Page posted="2006-07-28" visits="133" title="The Beauty of a Frost-Free Refrigerator"/>
<Page posted="2006-03-31" visits="316" title="How to Achieve Restful Sleep"/>
<Page posted="2006-09-21" visits="232" title="Buying Your First Car"/>
</Pages>

I have tried with following code and It's working fine.

    Dim Node As XmlNode = XmlDocumnet.SelectSingleNode("/Pages/Page/@visits[not(. <= ../preceding-sibling::Page/@visits) and not(. <=../following-sibling::Page/@visits)]")

    If Node IsNot Nothing AndAlso Node.Value <> "" Then
        MaxVisit= Convert.ToInt32(Node.Value) + 1
    End If

But If Visist attribute has duplicate value then it's not found properly. i.e. the maximum values does not exist if duplicate visit is found and also for empty visits.

For eg:

 <Page posted="2006-07-12" visits="214" title="Tire Swings for Grownups"/>
 <Page posted="2006-11-07" visits="214" title="Eliminate Hornets from Your Picnic"/>

or:

 <Page posted="2006-07-12" visits="" title="Tire Swings for Grownups"/>
 <Page posted="2006-11-07" visits="214" title="Eliminate Hornets from Your Picnic"/>
Was it helpful?

Solution

To return the first occurrence instead of no result in case there are multiple nodes with maximum visits, change your XPath to use < instead of <= :

/Pages/Page/@visits[
        not(. < ../preceding-sibling::Page/@visits) 
            and 
        not(. < ../following-sibling::Page/@visits)
        ]

UPDATE :

In addition to above XPath, to also filter out empty visits, you can try this way :

/Pages/Page/@visits[
        not(. < ../preceding-sibling::Page/@visits) 
            and 
        not(. < ../following-sibling::Page/@visits)
            and
        normalize-space(.)
        ]

OTHER TIPS

You could use the following Linq to Xml instead of querying the XmlDocument with XPath:

Dim el = XDocument.Parse(xmlInput)
Dim maxVisits = el.Descendants("Page") _
                  .Select(Function(x) New With { _
                                      .Title = x.Attribute("Title").Value, _
                                      .Visits = If(String.IsNullPrEmpty(x.Attribute.Value), 
                                                   0, 
                                                   Integer.Parse(x.Attribute("Visits").Value)) }) _
                  .OrderByDescending(Function(x) x.Visits) _
                  .FirstOrDefault()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top