从XML对象中选择具有给定值的属性

时间:2013-05-07 02:01:44

标签: c# xml

我有一个解析XML输入文件的程序。 XML有点被破坏了。我没有开发模式,也没有控制生成XML的程序。以下是我遇到问题的XML示例。

<object type="vdisk" >
<property name="mdisk_grp_id" value="many" />
<property name="mdisk_grp_name" value="many" />
<property name="mdisk_grp_id" value="10" />
<property name="mdisk_grp_name" value="VMAX5161" />
</object>

问题是同名的多个属性。显然这是不正确的。我需要选择没有“很多”作为值的那个。现在我的程序抓住了它,因为它首先发生。它破坏了程序中的其他内容。以下是我尝试过的内容。这是我的VDisk类的构造函数的部分列表。它似乎适用于输入文件中“vdisk”类型的某些对象,但不适用于其他对象。

 public VDisk(XElement element)
    {
var mdg = from mdgs in element.Descendants("property")
                  where
                      mdgs.Attribute("name").Value == "mdisk_grp_name"
                  select mdgs;

        foreach (XElement mdgp in mdg)
        {
            if (mdgp.Attribute("value").Value != "many")
            {
                MDiskGrpName = mdgp.Attribute("value").Value;
                break;

            }
        }
}

这是抛出异常的代码。没有任何实际命名为“many”的MDiskGroup。因此var变回空白。我可以捕获异常并继续,但我想将正确的数据导入VDisk MDiskGroupName属性。

var mdiskgrp = CurrentCluster.MDiskGroups.Where(mdg => mdg.Name == vdisk.MDiskGrpName);
                mdiskgrp.FirstOrDefault().VDiskList.Add(vdisk);

2 个答案:

答案 0 :(得分:1)

试试这个:

element.Descendants("property").Where(x => x.Attribute("name").Value == "mdisk_grp_name" && x.Attribute("value").Value != "many").First();

答案 1 :(得分:0)

你试图在一个程序中做很多事情。将任务分解为简单任务的管道。如果你想删除除了last之外的给定名称的每个属性,请将其作为预处理转换。它只有几行代码,并且将它分开意味着代码可以重用,因为它可以插入到使用此XML输入的任何管道中,而不是混乱您的“业务”逻辑。转型基本上是这样的:

<xsl:template match="object">
  <xsl:copy>
    <xsl:copy select="@*"/>
    <xsl:for-each-group select="Property" group-by="@name">
       <xsl:copy-of select="current-group()[last()]"/>
    </xsl:for-each-group>
  </xsl:copy>
</xsl:template>