Reputation: 2393
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
Upvotes: 4
Views: 23165
Reputation: 322
I found the easiest approach was to load the XML file as all lowercase and then just make sure that any subsequent XPath expressions were all lower-case.
Example:
var xmlDoc = new System.Xml.XmlDocument();
var rawFile = System.IO.File.ReadAllText(@"\Path\To\File.xml");
xmlDoc.LoadXml(rawFile.ToLower());
XmlNode node = xmlDoc.SelectSingleNode("//some/path[@attribute1='somevalue' and @attribute2='anothervalue']");
Upvotes: 0
Reputation: 680
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()));
Upvotes: 6
Reputation: 167716
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);
Upvotes: 1
Reputation: 243569
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()
.
Upvotes: 5
Reputation: 1900
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
Upvotes: 2