使用XPath选择节点时忽略节点名称的大小写

4

我有一个类似于这个问题SelectNodes with XPath ignoring cases的问题,但在我的情况下,大小写问题出现在名为'application'的节点中(有时是'Application',其他时候是'application')。

我应该如何应用另一个帖子中的解决方案?还是在这种情况下应该使用不同的解决方案?

xml:

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

在C# 3.5中:

XmlNode nodex= oXMLDoc1.SelectSingleNode("Application/forms/action/form/@uid")
nodex.Value="UniqueIDx";//nodex is null :S

1
你必须使用XPath吗?我个人会使用带有Where子句的LINQ to XML。Application/application始终是根节点吗?(如果是,那么您不能从中应用XPath吗?) - Jon Skeet
1
有趣...你能发一个使用LINQ to XML的例子吗?还有一个使用位置而不是名称作为第一个节点的XPATH示例吗?谢谢 ^^ - VSP
@JonSkeet 抱歉忘记直接回复您了,请查看上面的帖子。 - VSP
5个回答

6
我们可以将XML和变量转换为小写字母。
string value = "aBc";
XmlNode xmlnode = xmldoc.SelectSingleNode(string.Format("/some/path/add[translate(@key, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') = '{0}']", value.ToLower()));

谢谢您的回答,因为这是最通用的,所以它可以应用于其他情况。 - VSP
"/some/path/add" 是什么意思? - Varadha31590

5

仅需使用

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

当当前节点有一个名为“application”的子节点时,此选择器在所有情况下都能正确选择所需的属性,而且不区分大小写。

XSLT - 基于验证:

<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>

当对以下XML文档应用此转换时:

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

所选节点已被选择,并将其字符串值复制到输出中。
xyz

说明:

正确使用标准XPath函数name()translate()


2
首先要提到的是XML区分大小写,所以“Application”和“application”意义不同。看起来应该在生成该XML的代码中进行修复,但如果您无法控制它,那么可以尝试像这样使用XPath:
"Application/forms/action/form/@uid | application/forms/action/form/@uid"

| 运算符将组合从 xpath 返回的节点集,在这种情况下它将是其中之一。


是的,我知道XML是区分大小写的,但实际上生成的XML取决于第三方,所以这是必要的...你的方法很好,但我想知道使用LINQ to XML或通过位置获取第一个节点是否更优,因为在这个解决方案中,代码尝试获取两个节点... - VSP

1
如果根元素是唯一一个字母大小写可以改变的元素,那么你应该简单地执行例如:
XmlDocument doc = new XmlDocument();
doc.Load("input.xml");
XmlNode nodex= oXMLDoc1.DocumentElement.SelectSingleNode("forms/action/form/@uid");

正如评论中已经建议的那样。

使用XDocument,您可以执行例如:

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

[编辑] 有评论称第一个示例路径会抛出异常,这里是一个完整的示例,对我来说不会抛出异常,并使用了之前发布的相同路径:

            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);

尝试第一个示例时出现了NullReferenceException错误,改为使用以下代码成功:*/forms/action/form/@uid - VSP
根据您发布的示例,我认为我的建议应该有效。我将编辑我的帖子,展示一个完整的示例,对我来说不会抛出异常。 - Martin Honnen

0
我发现最简单的方法是将XML文件加载为全小写,然后确保任何后续的XPath表达式都是小写的。
示例:
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']");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接