【问题标题】:SelectNodes with XPath ignoring cases in node names带有 XPath 的 SelectNodes 忽略节点名称中的大小写
【发布时间】:2012-06-15 10:06:47
【问题描述】:

我有一个类似于SelectNodes with XPath ignoring cases 的问题,但在我的情况下,大写/小写问题出现在名为“应用程序”的节点中(有时是“应用程序”,有时是“应用程序”)。

我将如何应用其他帖子的解决方案?还是在这种情况下适用不同的方法?

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

【问题讨论】:

  • 你必须使用 XPath 吗?我个人会使用带有 Where 子句的 LINQ to XML。应用程序/应用程序始终是根节点吗? (如果是这样,你不能只应用 XPath 吗?)
  • 有趣...您能否发布一个使用 LINQ to XML 的示例?和第一个节点作为位置而不是名称的 XPATH 之一?谢谢^^
  • @JonSkeet Ups 我忘了直接回复你,请看上面的帖子

标签: c# xml xpath case-insensitive selectsinglenode


【解决方案1】:

我们可以将 xml 和我们的变量转换为小写。

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

【讨论】:

  • 感谢您的回答,因为这是最通用的,因此可以应用于其他情况
  • “/some/path/add”是什么意思??
【解决方案2】:

只需使用

*[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()

【讨论】:

    【解决方案3】:

    首先我想提一下 xml 是区分大小写的,所以 Application 意味着其他东西然后是 application,在我看来这应该在生成这个 xml 的代码中修复 但如果你无法控制它,可以试试这样的东西作为你的 xpath:

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

    该 |运算符将组合从两个 xpath 返回的节点集 在这种情况下,它将是一个或另一个

    【讨论】:

    • 是的,知道 xml 是区分大小写的,但实际上生成的 xml 依赖于第三方,所以这是需要的...您的方法工作正常,但我想知道是否可以使用 LINQ to XML 或获取位置上的第一个节点会更优化,因为在此解决方案中,代码会尝试获取两个节点...
    【解决方案4】:

    如果根元素是唯一可以改变字母大小写的元素,那么你应该简单地做例如

    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
    • 对于您发布的示例,我认为我的建议应该可行,我将编辑我的帖子以显示一个不会引发异常的完整示例。
    【解决方案5】:

    我发现最简单的方法是将 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']");
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-09
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 1970-01-01
      • 2010-10-17
      相关资源
      最近更新 更多