【问题标题】:Issue parsing XML string to xDocument将 XML 字符串解析为 xDocument 的问题
【发布时间】:2013-11-03 00:51:40
【问题描述】:

我从 Web API 的控制器接收到一个 XML 字符串,其构造如下所示:

private string CreateXDoc(IEnumerable<PassedJSONConverted> passed)
    {
        XNamespace xmlns = "http://host.adp.com";

        var doc = new XDocument(new XDeclaration("1.0", "utf-8", "yes"));

        var jobListElement = new XElement(xmlns + "JobXML");

        foreach (var objectItem in passed)
        {
            var loopElement = new XElement(xmlns + "JobsXML", new XElement(xmlns + "ID", objectItem.ID.ToString()), new XElement(xmlns + "Name", objectItem.Name), new XElement(xmlns + "Age", objectItem.Age.ToString()), new XElement(xmlns + "JobTitle", objectItem.JobTitle), new XElement(xmlns + "StartDate", objectItem.StartDate));

            jobListElement.Add(loopElement);
        }

        doc.Add(jobListElement);

        //Format without \n's
        return doc.ToString(SaveOptions.DisableFormatting);
    }

这很好,XML设置如下:

- <JobXML xmlns="http://host.xxx.com">
 - <JobsXML>
    <ID>1</ID> 
    <Name>Dave</Name> 
    <Age>23</Age> 
    <JobTitle>Developer</JobTitle> 
    <StartDate>10/24/2013 6:40:28 AM</StartDate> 
  </JobsXML>
- <JobsXML>
    <ID>2</ID> 
    <Name>John</Name> 
    <Age>44</Age> 
    <JobTitle>QA</JobTitle> 
    <StartDate>10/24/2013 6:40:28 AM</StartDate> 
  </JobsXML>
- <JobsXML>
    <ID>3</ID> 
    <Name>Dave</Name> 
    <Age>23</Age> 
    <JobTitle>Senior Developer</JobTitle> 
    <StartDate>10/24/2013 6:40:28 AM</StartDate> 
  </JobsXML>
 </JobXML>

当我将其作为字符串返回并尝试将其解析回 xDoc 时,如下所示:

private static string HandleResponse(HttpWebResponse httpResponse)
    {
        using (var responseReader = new StreamReader(httpResponse.GetResponseStream(), Encoding.UTF8))

        {
            string responsePayload = responseReader.ReadToEnd();

            var newxDoc = XDocument.Parse(responsePayload);

            return responsePayload;
        }
    }

运行时字符串'responsePayLoad'设置如下:

 "<JobXML xmlns=\"http://host.adp.com\"><JobsXML><ID>1</ID><Name>Dave</Name><Age>23</Age><JobTitle>Developer</JobTitle><StartDate>10/24/2013 6:45:22 AM</StartDate></JobsXML><JobsXML><ID>2</ID><Name>John</Name><Age>44</Age><JobTitle>QA</JobTitle><StartDate>10/24/2013 6:45:22 AM</StartDate></JobsXML><JobsXML><ID>3</ID><Name>Dave</Name><Age>23</Age><JobTitle>Senior Developer</JobTitle><StartDate>10/24/2013 6:45:22 AM</StartDate></JobsXML></JobXML>"

这给了我一个例外:'newxDoc' 对象:

XmlException 未处理。根级别的数据无效。第 1 行,位置 1。

谁能告诉我哪里出错了?

【问题讨论】:

  • 我已经在 responsePayLoad XML 上尝试了 XDocument.Parse() 并且没有出错。
  • 我遇到了类似的问题,发现它与编码有关。在StreamReader 中将Encoding 设置为Default 对我有用。

标签: c# xml api parsing xmlexception


【解决方案1】:

问题是您的 responsePayLoad 字符串不是有效的 XML。

你的问题在这里:

"<JobXML xmlns=\"http://host.adp.com\">

在字符串的开头和结尾处存在引号字符以及引号之前的反斜杠会导致 XML 格式错误。如果您的字符串在开头和结尾没有这些引号以及反斜杠,则 XML 将是有效的,即这将使 XML 格式正确:

<JobXML xmlns="http://host.adp.com">...<\JobXML>

至于为什么会出现这个问题,可能是因为您创建 XDocument 的方式。 Microsoft 文档here 中的示例表明,使用特定 XDeclaration 的 XDocument 应使用以下构造函数进行实例化:

XDocument(XDeclaration, Object[])

所以我会尝试重构您的代码以使我们使用这种方法,例如

private string CreateXDoc(IEnumerable<PassedJSONConverted> passed)
{
    XNamespace xmlns = "http://host.adp.com";

    var xdec = new XDeclaration("1.0", "utf-8", "yes");

    var jobListElement = new XElement(xmlns + "JobXML");

    foreach (var objectItem in passed)
    {
        var jobXml = new XElement(xmlns + "JobsXML", 
                            new XElement(xmlns + "ID", objectItem.ID.ToString()), 
                            new XElement(xmlns + "Name", objectItem.Name), 
                            new XElement(xmlns + "Age", objectItem.Age.ToString()), 
                            new XElement(xmlns + "JobTitle", objectItem.JobTitle), 
                            new XElement(xmlns + "StartDate", objectItem.StartDate));

        jobListElement.Add(jobXml);
    }

    var doc = new XDocument(
        xdec,
        new XElement(jobListElement)
    );

    //Format without new lines
    return doc.ToString(SaveOptions.DisableFormatting);
}

如果这不起作用,请尝试关闭 CreateXDoc 中的禁用格式,即

return doc.ToString();

【讨论】:

    【解决方案2】: