Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/337.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .NET:将嵌套XML结构中的所有值按顺序写入字符串_C#_.net_Xml - Fatal编程技术网

C# .NET:将嵌套XML结构中的所有值按顺序写入字符串

C# .NET:将嵌套XML结构中的所有值按顺序写入字符串,c#,.net,xml,C#,.net,Xml,注意:我的最终解决方案张贴在这篇文章的底部 我试图构建一个包含XML对象中包含的所有字段/消息的字符串,以便生成的字符串需要保留错误的结构信息 我的问题是结构可以嵌套。我努力只选择一个级别/后代,而不选择所有名为“field”或“Error”的元素。我对LINQXML了解不够,无法抓住第一个,检查存在哪些子节点,然后从那里继续 对象的结构如下所示: <PingResponse> <Status>denied</Status> <Error

注意:我的最终解决方案张贴在这篇文章的底部

我试图构建一个包含XML对象中包含的所有字段/消息的字符串,以便生成的字符串需要保留错误的结构信息

我的问题是结构可以嵌套。我努力只选择一个级别/后代,而不选择所有名为“field”或“Error”的元素。我对LINQXML了解不够,无法抓住第一个,检查存在哪些子节点,然后从那里继续

对象的结构如下所示:

<PingResponse>
    <Status>denied</Status>
    <Errors>
        <Error>
            <Field>lead</Field>
            <Errors>
                <Error>
                    <Field>drivers</Field>
                    <Errors>
                        <Error>
                            <Field>gender</Field>
                            <Message>This field is required.</Message>
                        </Error>
                        <Error>
                            <Field>license_status</Field>
                            <Message>This field is required.</Message>
                        </Error>
                        <Error>
                            <Field>relationship</Field>
                            <Message>This field is required.</Message>
                        </Error>
                    </Errors>
                </Error>
            </Errors>
        </Error>
    </Errors>
</PingResponse>
注意事项:

错误将始终至少包含一个错误元素

错误可能包含:

1) 字段+错误或

2) 字段+消息,孩子们

我解决这个问题的计划是:

protected string errorDecoder(XElement node)
{
StringBuilder sb = new StringBuilder();

// PseudoCode     
// 1) Check nodes within element 
// 2) If "Field" or "Message" present, append those values to **sb** 
// 3) If "Errors" present, call this method with this node, to finish building string through recursion. 
// 4) Ultimately return the final string when all elements have been processed

returns string;
}
我一直不知道如何读取/返回只有1级深度的后代。尝试按名称选择Decentants时,所有具有该名称的字段。如果我尝试选择元素的第一个实例,我可能会在不经意间跳到树下太远

我怎样才能:

1) 检查存在哪些下一级子级

2) 如何只抓住下一级儿童的价值观,这样我就可以随心所欲地表达我的信息

或者你对产生相同结果的解决方案的想法

我的最终解决方案: 我发现我最大的问题是理解LINQ查询。一旦我发现我应该只查询“Field”元素,一切都很顺利。如果元素存在,我将检索字段值和消息值。谢谢大家的帮助

StringBuilder responseReason = new StringBuilder("Denied: ");
var errorCollection =  XDocument.Parse(result)
                                .Descendants()
                                .Where(x => x.Element("Field") != null);

foreach (var error in errorCollection)
{
    responseReason.Append(" Field: " + error.Element("Field").Value.ToString());
    responseReason.Append(error.Element("Message") != null ? " Message: " + error.Element("Message").Value.ToString() : "");
}

response = responseReason.ToString();
匹配所有级别的子体

您需要使用以获取直接子节点,这将为您提供“仅下一级子节点”


要找到下一个级别有这样的子节点,您需要找到是否存在这样的子节点(使用
子节点
),并可能使用每个节点的
父节点
,直到返回到当前节点(这是一种可能的算法,不确定它的性能如何)。这将为您提供深度信息。

虽然XML文件中的嵌套级别在很大程度上引入了顺序,但在下面引用的文件部分中没有给出顺序。尽管大多数XML解析器应该按照文件中提供的顺序返回它们,但这不是XML标准的要求,任何XML解析器都可以按照任何顺序自由返回以下
块:

<Errors>
    <Error>
        <Field>gender</Field>
        <Message>This field is required.</Message>
    </Error>
    <Error>
        <Field>license_status</Field>
        <Message>This field is required.</Message>
    </Error>
    <Error>
        <Field>relationship</Field>
        <Message>This field is required.</Message>
    </Error>
</Errors>

性别
此字段必填。
许可证状态
此字段必填。
关系
此字段必填。

我相信这会满足您的要求:

XDocument doc = XDocument.Parse(xml);

string errors =
    (
        from e in doc.Descendants("Error")
        let field = (string)e.Element("Field")
        let message = (string)e.Element("Message")
        where field != null
        select new { field, message }
    ).Aggregate(
        new StringBuilder(),
        (sb, o) => (sb.Length == 0 ? sb : sb.Append(' ')).AppendFormat(
            o.message != null ? "Field: {0} Message: {1}" : "Field: {0}",
            o.field,
            o.message),
        sb => sb.ToString());

我最初对使用LINQ查询时后代的工作方式感到困惑。我发现最简单的方法是获取包含“Field”元素的所有元素,只查找消息元素。循环允许我最终按顺序解开所有字段/消息。
XDocument doc = XDocument.Parse(xml);

string errors =
    (
        from e in doc.Descendants("Error")
        let field = (string)e.Element("Field")
        let message = (string)e.Element("Message")
        where field != null
        select new { field, message }
    ).Aggregate(
        new StringBuilder(),
        (sb, o) => (sb.Length == 0 ? sb : sb.Append(' ')).AppendFormat(
            o.message != null ? "Field: {0} Message: {1}" : "Field: {0}",
            o.field,
            o.message),
        sb => sb.ToString());