Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. The Weird and The Wonderful
  4. XPath string comparisons

XPath string comparisons

Scheduled Pinned Locked Moved The Weird and The Wonderful
xmlcsharpdatabasedebugging
4 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kmoorevs
    wrote on last edited by
    #1

    I spent way too long yesterday discovering that XPath 1.0 does not support string comparisons for anything but equal as the args are automatically converted to number...not much use when you are trying to filter an xml document with a date attribute!...or any string which doesn't convert to number) The weird thing about this is that this was VB6 code I am migrating...meaning, it works fine with ancient XML libs, but not a modern framework. (currently targeting 4.0) Such is progress! :laugh: I guess I'm used to going forward, not backward! :) They may have fixed/added this in XPath 2.0 which I think is available under .NET 4.6.2 or something. I chose another method not involving XPath once I discovered why no results were being returned. It was the hours spent cursing and swearing, not understanding why something that looks like it should work doesn't. No error, just no results. It was easy to understand why once I knew that the rules had changed. For clarity, I'm providing a sample xml doc and code: The sample xml document was taken from MS sample code. I only added the publish_date attribute as this was akin to my actual usage.

    The Handmaid's Tale  
      
      Margaret  
      Atwood  
      
    19.95  
    
    
    The Poisonwood Bible  
      
      Barbara  
      Kingsolver  
      
    11.99  
    
    
    The Bean Trees  
      
      Barbara  
      Kingsolver  
      
    5.99  
    

    and now, the code:

    Dim xmlDoc As New System.Xml.XmlDocument
    Dim xmlNodes As System.Xml.XmlNodeList
    Dim root As System.Xml.XmlNode
    xmlDoc.Load("..\bookstore.xml")
    Dim nsmgr As System.Xml.XmlNamespaceManager = New System.Xml.XmlNamespaceManager(xmlDoc.NameTable)
    nsmgr.AddNamespace("bk", "urn:newbooks-schema")
    root = xmlDoc.DocumentElement
    'this returns 1 node/record
    xmlNodes = root.SelectNodes("descendant::bk:book[@publish_date = '1901-10-29']", nsmgr)

    Debug.Print(x

    Richard DeemingR 1 Reply Last reply
    0
    • K kmoorevs

      I spent way too long yesterday discovering that XPath 1.0 does not support string comparisons for anything but equal as the args are automatically converted to number...not much use when you are trying to filter an xml document with a date attribute!...or any string which doesn't convert to number) The weird thing about this is that this was VB6 code I am migrating...meaning, it works fine with ancient XML libs, but not a modern framework. (currently targeting 4.0) Such is progress! :laugh: I guess I'm used to going forward, not backward! :) They may have fixed/added this in XPath 2.0 which I think is available under .NET 4.6.2 or something. I chose another method not involving XPath once I discovered why no results were being returned. It was the hours spent cursing and swearing, not understanding why something that looks like it should work doesn't. No error, just no results. It was easy to understand why once I knew that the rules had changed. For clarity, I'm providing a sample xml doc and code: The sample xml document was taken from MS sample code. I only added the publish_date attribute as this was akin to my actual usage.

      The Handmaid's Tale  
        
        Margaret  
        Atwood  
        
      19.95  
      
      
      The Poisonwood Bible  
        
        Barbara  
        Kingsolver  
        
      11.99  
      
      
      The Bean Trees  
        
        Barbara  
        Kingsolver  
        
      5.99  
      

      and now, the code:

      Dim xmlDoc As New System.Xml.XmlDocument
      Dim xmlNodes As System.Xml.XmlNodeList
      Dim root As System.Xml.XmlNode
      xmlDoc.Load("..\bookstore.xml")
      Dim nsmgr As System.Xml.XmlNamespaceManager = New System.Xml.XmlNamespaceManager(xmlDoc.NameTable)
      nsmgr.AddNamespace("bk", "urn:newbooks-schema")
      root = xmlDoc.DocumentElement
      'this returns 1 node/record
      xmlNodes = root.SelectNodes("descendant::bk:book[@publish_date = '1901-10-29']", nsmgr)

      Debug.Print(x

      Richard DeemingR Offline
      Richard DeemingR Offline
      Richard Deeming
      wrote on last edited by
      #2

      That doesn't sound right at all. String Functions[^] Here's a demo: XPath String Functions | C# Online Compiler | .NET Fiddle[^] You must be doing something wrong. :laugh:


      "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

      "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

      K 1 Reply Last reply
      0
      • Richard DeemingR Richard Deeming

        That doesn't sound right at all. String Functions[^] Here's a demo: XPath String Functions | C# Online Compiler | .NET Fiddle[^] You must be doing something wrong. :laugh:


        "These people looked deep within my soul and assigned me a number based on the order in which I joined." - Homer

        K Offline
        K Offline
        kmoorevs
        wrote on last edited by
        #3

        Richard Deeming wrote:

        You must be doing something wrong

        :laugh: Without a doubt...I'm taking a big risk here, exposing my ignorance! :laugh: I've edited the OP with a sample for clarity. I really didn't intend to use the forum for QA, but I think maybe I was a little vague on the exact problem. Thanks! :)

        "Go forth into the source" - Neal Morse

        Richard DeemingR 1 Reply Last reply
        0
        • K kmoorevs

          Richard Deeming wrote:

          You must be doing something wrong

          :laugh: Without a doubt...I'm taking a big risk here, exposing my ignorance! :laugh: I've edited the OP with a sample for clarity. I really didn't intend to use the forum for QA, but I think maybe I was a little vague on the exact problem. Thanks! :)

          "Go forth into the source" - Neal Morse

          Richard DeemingR Offline
          Richard DeemingR Offline
          Richard Deeming
          wrote on last edited by
          #4

          OK, the "less than" and "greater than" operators don't work for strings, as per the specification:

          XML Path Language (XPath)[^]:

          When neither object to be compared is a node-set and the operator is <=, <, >= or >, then the objects are compared by converting both objects to numbers and comparing the numbers according to IEEE 754.

          I'd be very surprised if that wasn't also the case with the old MSXML library. But then again, it was written by 90's Microsoft - they weren't the best at sticking to the specifications! :-D There's no obvious sign of Microsoft implementing XPath 2 or 3 in .NET; there's an open suggestion from 2013[^] which is "under consideration", with no sign of any action. There's also an MSDN blog post from 2004[^] suggesting they would be working on XQuery instead. Again, no sign of any progress on that front. It's also worth pointing out that you can't use the less than or greater than operators on strings in .NET code either. Instead, you have to use the CompareTo method. You can get close by using LINQ to XML, but that obviously requires you to load the entire document into memory:

          var doc = XDocument.Parse(@"<?xml version='1.0'?>
          <bookstore xmlns=""urn:newbooks-schema"">
          <book genre=""novel"" style=""hardcover"" publish_date=""1825-04-02"">
          ...
          </bookstore>");

          var nodes = doc.Descendants(doc.Root.Name.Namespace + "book")
          .Where(el => ((string)el.Attribute("publish_date")).CompareTo("1901-10-29") >= 0);

          // Or:
          var nodes = doc.Descendants(doc.Root.Name.Namespace + "book")
          .Where

          "These people looked deep within my soul and assigned me a number based on the order in which I joined" - Homer

          1 Reply Last reply
          0
          Reply
          • Reply as topic
          Log in to reply
          • Oldest to Newest
          • Newest to Oldest
          • Most Votes


          • Login

          • Don't have an account? Register

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • World
          • Users
          • Groups