【问题标题】:How do I check particular attributes exist or not in XML?如何检查 XML 中是否存在特定属性?
【发布时间】:2011-11-03 10:44:27
【问题描述】:

部分XML内容:

<section name="Header">
  <placeholder name="HeaderPane"></placeholder>
</section>

<section name="Middle" split="20">
  <placeholder name="ContentLeft" ></placeholder>
  <placeholder name="ContentMiddle"></placeholder>
  <placeholder name="ContentRight"></placeholder>
</section>

<section name="Bottom">
  <placeholder name="BottomPane"></placeholder>
</section>

我想检查每个节点,如果属性split存在,尝试在变量中分配一个属性值。

在一个循环中,我尝试:

foreach (XmlNode xNode in nodeListName)
{
    if(xNode.ParentNode.Attributes["split"].Value != "")
    {
        parentSplit = xNode.ParentNode.Attributes["split"].Value;
    }
}

但是如果条件只检查值而不检查属性的存在,那我就错了。我应该如何检查属性是否存在?

【问题讨论】:

  • 虽然在问这个问题时这可能不是真的,但现在有一个XmlElement.HasAttribute Method,对我来说,它似乎非常适合这种用例。以防万一有人偶然发现这个......

标签: c# xml


【解决方案1】:

您实际上可以直接索引到 Attributes 集合中(如果您使用的是 C# 而不是 VB):

foreach (XmlNode xNode in nodeListName)
{
  XmlNode parent = xNode.ParentNode;
  if (parent.Attributes != null
     && parent.Attributes["split"] != null)
  {
     parentSplit = parent.Attributes["split"].Value;
  }
}

【讨论】:

  • 如果节点的属性为零,则抛出异常。您需要首先测试 Attributes 集合不为空。
  • 我猜是新的语法糖:if (parent?.Attributes["split"] != null)
  • 我觉得更像if (parent.Attributes?["name"] != null)
【解决方案2】:

如果您的代码正在处理XmlElements 对象(而不是XmlNodes),则有XmlElement.HasAttribute(string name) 方法。

因此,如果您只是在元素上查找属性(从 OP 中看起来),那么将其强制转换为元素,检查 null,然后使用 HasAttribute 方法可能会更可靠。

foreach (XmlNode xNode in nodeListName)
{
  XmlElement xParentEle = xNode.ParentNode as XmlElement;
  if((xParentEle != null) && xParentEle.HasAttribute("split"))
  {
     parentSplit = xParentEle.Attributes["split"].Value;
  }
}

【讨论】:

    【解决方案3】:

    仅适用于新手:最新版本的 C# 允许使用 ? 运算符来检查空值分配

    parentSplit = xNode.ParentNode.Attributes["split"]?.Value;
    

    【讨论】:

      【解决方案4】:

      您可以使用 LINQ to XML,

      XDocument doc = XDocument.Load(file);
      
      var result = (from ele in doc.Descendants("section")
                    select ele).ToList();
      
      foreach (var t in result)
      {
          if (t.Attributes("split").Count() != 0)
          {
              // Exist
          }
      
          // Suggestion from @UrbanEsc
          if(t.Attributes("split").Any())
          {
      
          }
      }
      

       XDocument doc = XDocument.Load(file);
      
       var result = (from ele in doc.Descendants("section").Attributes("split")
                     select ele).ToList();
      
       foreach (var t in result)
       {
           // Response.Write("<br/>" +  t.Value);
       }
      

      【讨论】:

      • +1 用于 Linq to XML。而不是 Count() != 0 你可以使用 Any()
      • @UrbanEsc - 只是出于好奇,使用 Any() 而不是 Count() 有什么好处吗?
      【解决方案5】:
      var splitEle = xn.Attributes["split"];
      
      if (splitEle !=null){
          return splitEle .Value;
      }
      

      【讨论】:

        【解决方案6】:

        编辑

        忽略 - 您不能使用 ItemOf (这是我在测试之前输入的内容)。如果我能弄清楚怎么做,我会删除文本……或者我会简单地删除答案,因为它最终是错误的和无用的。

        结束编辑

        您可以使用 XmlAttributesCollection 中的ItemOf(string) 属性来查看该属性是否存在。如果未找到,则返回 null。

        foreach (XmlNode xNode in nodeListName)
        {
            if (xNode.ParentNode.Attributes.ItemOf["split"] != null)
            {
                 parentSplit = xNode.ParentNode.Attributes["split"].Value;
            }
        }
        

        XmlAttributeCollection.ItemOf Property (String)

        【讨论】:

        • 我的意思是检查属性split 存在。如果属性存在,则在变量中分配属性值。谢谢。
        • @Shree - 上面的代码将检查属性“split”是否存在,如果存在,如果将属性的值分配给parentSplit。请注意,如果 nodeListName 中有多个 XmlNode 的 ParentNode 具有“split”属性,则列表中的最后一个将分配给 parentSplit,覆盖之前的(如果有的话)。
        • ItemOf 实际上是指向 Attribute 集合的直接索引。
        • ItemOf 是与此交互的 VB 方式。直接索引到集合中是 C# 方法。
        【解决方案7】:

        您可以使用 GetNamedItem 方法来检查该属性是否可用。如果返回 null,则它不可用。这是您进行该检查的代码:

        foreach (XmlNode xNode in nodeListName)
        {
            if(xNode.ParentNode.Attributes.GetNamedItem("split") != null )
            {
                if(xNode.ParentNode.Attributes["split"].Value != "")
                {
                    parentSplit = xNode.ParentNode.Attributes["split"].Value;
                }
            }  
        }
        

        【讨论】:

        • 正如其他人在这里提到的,在继续之前检查 xNode.ParentNode.Attributes 是否为空总是好的。
        【解决方案8】:

        处理这种情况的另一种方法是异常处理。

        每次调用不存在的值时,您的代码都会从异常中恢复并继续循环。在 catch 块中,当表达式 (... != null) 返回 false 时,您可以像在 else 语句中写下错误一样处理错误。当然,抛出和处理异常是一项相对昂贵的操作,根据性能要求可能并不理想。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-06-09
          • 2017-09-25
          • 2011-01-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多