0

这是XML

获取此 ResultCode 属性,如果错误则查找所有产品的子节点

   <PRODUCT Action="Result" ResultCode="ERROR" ResultText="An error occurred in a child   element.">            <PNO>9723151113</PNO>
       <CATALOG_NO ResultCode="ERROR" ResultText="Invalid entry for this field.">1134</CATALOG_NO>
   </PRODUCT>

所以首先我想检查是否有任何节点的属性有 ERROR ,然后选择子节点并查找后代子节点有错误并使用 LINQ 获取该节点。如上所述,查找 Cust 下的所有节点以检查属性“ResultCode”,如果它具有错误值,则选择该节点并查找其子节点以找出确切的错误。Cust -> 任何有错误的节点?-> 产品 => 选择产品 => 查看产品下的所有子节点 => 选择 ERROR 属性节点。

我不想放一个逻辑来解析循环中的每个节点,所以认为使用 linq 会很容易。知道如何使用 Linq 查询来实现这一点吗?

4

3 回答 3

1

试试这个:

var xDoc = XDocument.Load(@"YourXML.xml");
var xElementWithErrors = (from xElem in doc.Descendants()
                          where xElem.Attribute("ResultCode").Value == "ERROR"
                          select xElem).ToList();

ResultCode 为“ERROR”的 Product 标记的所有子项都将填充到列表中xElementWithErrors

于 2013-04-18T00:53:18.987 回答
0

如果我理解您的问题正确,您只想获取具有属性的最里面的元素ResultCode="ERROR"。因为您的示例数据<PRODUCT>不应该出现在结果中,因为它有一个带有ResultCode="ERROR".

Descendants方法返回文档中的所有后代元素。因此,仅按属性过滤将包括<PRODUCT>节点。所以你需要为每个元素的子元素添加一个检查:

var doc = XDocument.Load("Test.xml");

var errors = doc.Descendants()
                .Where(e => e.Attribute("ResultCode") != null &&
                            e.Attribute("ResultCode").Value == "ERROR" &&
                            !e.Elements().Any(c => c.Attribute("ResultCode") != null &&
                                                   c.Attribute("ResultCode").Value == "ERROR"));

这将只返回那些没有任何错误子元素的元素。

ResultCode请注意,如果您的 XML 中的每个节点都有一个属性,则可以省略对 null 的检查。如果不是,您将获得一个NullReferenceException. 我建议为该检查编写一个小辅助方法:

public static bool HasError(XElement element)
{
    var resultCode = element.Attribute("ResultCode");
    return resultCode != null && resultCode.Value == "ERROR";
}

var errors = doc.Descendants()
                .Where(e => HasError(e) && !e.Elements().Any(c => HasError(c)));

另请注意,这将返回ResultCode="ERROR"即使其父级没有错误的元素。

如果您的要求是只有在其父元素也有错误时才应将元素包含在结果中,并且如果您不确定 XML 是否总是这样形成,您将需要编写一个递归函数:

public static IEnumerable<XElement> InnermostErrors(XElement root)
{
    var resultCode = root.Attribute("ResultCode");
    if (resultCode == null || resultCode.Value != "ERROR")
    {
        yield break;
    }

    var childrenWithError = root.Elements().Where(e => HasError(e));
    if (!childrenWithError.Any())
    {
        yield return root;
    }

    foreach (var inner in childrenWithError.SelectMany(e => InnermostErrors(e)))
    {
        yield return inner;
    }
}
于 2013-04-18T17:32:20.043 回答
0

使用 XDocument,您可以首先检查属性值为 的任何节点,ERROR然后还可以像这样选择其父节点

var doc = XDocument.Load(...);

var result = doc.Descendants()
    .Where(n => n.Attribute("ResultCode").Value == "ERROR")
    .Select(n => new { n.Parent, ActualNode = n });

您可能想要检查是否Parent不为空,并过滤您实际上不想处理的节点类型。如果不了解更多关于您在这里想要实现的目标,就很难为您提供更多帮助。希望这能让你开始。

于 2013-04-18T00:41:05.153 回答