SelectNodes with XPath ignoring cases in node names

20,586

Solution 1

We may convert xml and our variables to lower case.

string value = "aBc";
XmlNode xmlnode = xmldoc.SelectSingleNode(string.Format("/some/path/add[translate(@key, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = '{0}']", value.ToLower()));

Solution 2

Just use:

*[translate(name(), 'APPLICATION', 'application')='application']
     /forms/action/form/@uid

This selects the wanted attribute correctly in all cases when the current (initial context) node has a child with name, that is any capitalization of the string "application".

XSLT - based verification:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

 <xsl:template match="/">
     <xsl:value-of select=
      "*[translate(name(), 'APPLICATION', 'application')='application']
          /forms/action/form/@uid"/>
 </xsl:template>
</xsl:stylesheet>

When this transformation is applied on the following XML document:

<aPPliCatioN>
 <forms>
   <action>
    <form uid="xyz"/>
   </action>
 </forms>
</aPPliCatioN>

the wanted node is selected and its string value is copied to the output:

xyz

Explanation:

Proper use of the standard XPath functions name() and translate().

Solution 3

First of all I want to mention that xml is case sensitive, so Application means something else then application, looks to me this should be fixed in the code that generates this xml but if you have no control over that maybe try something like this as your xpath:

"Application/forms/action/form/@uid | application/forms/action/form/@uid"

The | operator will combine the node-sets that are returned from both xpath's in this case it will be one or the other

Solution 4

If the root element is the only element where the case of letters can change then you should simply do e.g.

XmlDocument doc = new XmlDocument();
doc.Load("input.xml");
XmlNode nodex= oXMLDoc1.DocumentElement.SelectSingleNode("forms/action/form/@uid");

as already suggested in a comment.

With XDocument you would do e.g.

XDocument doc = XDocument.Load("input.xml");
doc.Root.Element("forms").Element("action").Element("form").SetAttributeValue("uid", "UniqueIDx");

[edit] A comment claims the first example path throws an exception, here is a complete sample that does not throw an exception for me and uses the same path a posted before:

            string xml = @"<application>
  <forms>
    <action type=""update"">
      <form uid="""" >
      </form>
    </action>
  </forms>
</application>";
            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);
            XmlNode nodex = doc.DocumentElement.SelectSingleNode("forms/action/form/@uid");
            nodex.Value = "UniqueIDx";

            doc.Save(Console.Out);
Share:
20,586
VSP
Author by

VSP

Updated on August 18, 2021

Comments

  • VSP
    VSP over 2 years

    I have a problem similar to the question SelectNodes with XPath ignoring cases but in my case the uppercase/lowercase problem is in the node with the name 'application' (Sometimes is 'Application' other times 'application').

    How would i apply the solution of the other post? or a different one applies in this case?

    xml:

    <?xml version="1.0" encoding="utf-16" ?>
    <application>
      <forms>
        <action type="update">
          <form uid="" >
          </form>
        </action>
      </forms>
    </application>
    

    In C# 3.5:

    XmlNode nodex= oXMLDoc1.SelectSingleNode("Application/forms/action/form/@uid")
    nodex.Value="UniqueIDx";//nodex is null :S
    
  • VSP
    VSP almost 12 years
    Yep knew the xml is case sensitive but effectively the xml generated depended on a third party so this was needed... Your method works fine but i wanted to know if maybe with LINQ to XML or getting the first node by possition would be more optimal as in this solution the code tries to get both nodes...
  • VSP
    VSP almost 12 years
    Trying your first example failed with a nullreferenceexception, worked instead with: */forms/action/form/@uid
  • Martin Honnen
    Martin Honnen almost 12 years
    With the sample you posted I think my suggestion should work, I will edit my post to show a complete example that does not throw an exception for me.
  • VSP
    VSP almost 9 years
    Thanks for the answer, as this is the most generic one so it can be applied in other situations
  • Varadha31590
    Varadha31590 almost 8 years
    what does the "/some/path/add" means ??