【问题标题】:Select xs:element from xdocument in c#在c#中从xdocument中选择xs:element
【发布时间】:2017-05-24 09:00:20
【问题描述】:

我有一个包含多组数据的 xdocument,我希望能够选择特定 xs:element 的数据。

例如我有这段代码:

// get xml string
var xmlResponse = _traineeCommands.GetTraineeDetails(personId.ToString());

// parse to xdocument
var doc = XDocument.Parse(xmlResponse);

// select specific element and children
var traineeDetails = doc.Descendants("xs:element")
     .Select(x => (string) x.Attribute("name") == "TraineeDetails");

这是我的堆栈跟踪:

{
  "Message": "An error has occurred.",
  "ExceptionMessage": "The ':' character, hexadecimal value 0x3A, cannot be included in a name.",
  "ExceptionType": "System.Xml.XmlException",
  "StackTrace": "   at System.Xml.XmlConvert.VerifyNCName(String name, ExceptionType exceptionType)\r\n   at System.Xml.Linq.XName..ctor(XNamespace ns, String localName)\r\n   at System.Xml.Linq.XNamespace.GetName(String localName)\r\n   at IceServices.IpdApi.Controllers.JobController.GetTraineeDetailsForIpd(Int32 personId) in C:\\Users\\GOWDY_N\\Source\\Repos\\IceServices\\IceServices.IpdApi\\Controllers\\JobController.cs:line 134\r\n   at IceServices.IpdApi.Controllers.JobController.<Get>d__6.MoveNext() in C:\\Users\\GOWDY_N\\Source\\Repos\\IceServices\\IceServices.IpdApi\\Controllers\\JobController.cs:line 66\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Threading.Tasks.TaskHelpersExtensions.<CastToObject>d__3`1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}

这是整个 xml:

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
    xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <soap:Body>
        <GetIPDTraineeDetailsResponse
            xmlns="http://iris.co.uk/">
            <GetIPDTraineeDetailsResult>
                <xs:schema id="NewDataSet"
                    xmlns=""
                    xmlns:xs="http://www.w3.org/2001/XMLSchema"
                    xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
                    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
                        <xs:complexType>
                            <xs:choice minOccurs="0" maxOccurs="unbounded">
                                <xs:element name="TraineeDetails">
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:element name="ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="TRAINEE_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="ORG_REGISTRATION_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="TRAINING_SCHEME_TITLE" type="xs:string" minOccurs="0" />
                                            <xs:element name="SELF_MANAGED" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="TRAINING_START_DATE" type="xs:string" minOccurs="0" />
                                            <xs:element name="ANNUAL_REVIEW_STATUS" type="xs:string" minOccurs="0" />
                                            <xs:element name="SCE_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="SCE_FORENAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="SCE_SURNAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="SCE_NAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="DE_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="DE_NAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="DE_PERSON_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="DE_FORENAMES" type="xs:string" minOccurs="0" />
                                            <xs:element name="DE_FORENAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="DE_SURNAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="DE_EMAIL_ADDRESS" type="xs:string" minOccurs="0" />
                                            <xs:element name="MENTOR_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="MENTOR_FORENAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="MENTOR_SURNAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="MENTOR_NAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="MENTOR_EMAIL" type="xs:string" minOccurs="0" />
                                            <xs:element name="MENTOR_PERSONID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="SELECTED_LEVEL" type="xs:string" minOccurs="0" />
                                            <xs:element name="SELECTED_LEVEL_DESCRIPTION" type="xs:string" minOccurs="0" />
                                            <xs:element name="TRAINEE_STATUS" type="xs:string" minOccurs="0" />
                                            <xs:element name="TRAINEE_STATUS_DESCR" type="xs:string" minOccurs="0" />
                                            <xs:element name="REQUESTED_DE_PERSON_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="REQUESTED_DE_SURNAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="REQUESTED_DE_FORENAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="PENDING_DE_EMAIL" type="xs:string" minOccurs="0" />
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
                                <xs:element name="PersonDetails">
                                    <xs:complexType>
                                        <xs:sequence>
                                            <xs:element name="ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="FORENAMES" type="xs:string" minOccurs="0" />
                                            <xs:element name="FORENAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="SURNAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="DOB" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_NAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_ADDRESS_1" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_ADDRESS_2" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_ADDRESS_3" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_TOWN" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_STATE" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_COUNTRY" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYER_POSTCODE" type="xs:string" minOccurs="0" />
                                            <xs:element name="REASON_NOT_WORKING" type="xs:string" minOccurs="0" />
                                            <xs:element name="IPD_STATUS" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="PAYMENT_RECEIVED" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="SM_PRODUCT_DESC" type="xs:string" minOccurs="0" />
                                            <xs:element name="SM_PRODUCT_PRICE" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="ORIGINAL_TRAINING_START_DATE" type="xs:string" minOccurs="0" />
                                            <xs:element name="REVIEW_DATE" type="xs:string" minOccurs="0" />
                                            <xs:element name="TRANSFER_DATE" type="xs:string" minOccurs="0" />
                                            <xs:element name="ELIGIBLE_LEVEL" type="xs:string" minOccurs="0" />
                                            <xs:element name="ELIGIBLE_LEVEL_DESCRIPTION" type="xs:string" minOccurs="0" />
                                            <xs:element name="DEFAULT_LEVEL" type="xs:string" minOccurs="0" />
                                            <xs:element name="DEFAULT_LEVEL_DESCRIPTION" type="xs:string" minOccurs="0" />
                                            <xs:element name="PERSON_AIM" type="xs:string" minOccurs="0" />
                                            <xs:element name="EMPLOYEE_NUMBER" type="xs:string" minOccurs="0" />
                                            <xs:element name="IPD_SIGNUP_DATE" type="xs:string" minOccurs="0" />
                                            <xs:element name="REQUESTED_MENTOR_PERSON_ID" type="xs:decimal" minOccurs="0" />
                                            <xs:element name="REQUESTED_MENTOR_SURNAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="REQUESTED_MENTOR_FORENAME" type="xs:string" minOccurs="0" />
                                            <xs:element name="PENDING_MENTOR_EMAIL" type="xs:string" minOccurs="0" />
                                            <xs:element name="PENDING_AIM" type="xs:string" minOccurs="0" />
                                        </xs:sequence>
                                    </xs:complexType>
                                </xs:element>
                            </xs:choice>
                        </xs:complexType>
                    </xs:element>
                </xs:schema>
                <diffgr:diffgram
                    xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"
                    xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
                    <NewDataSet
                        xmlns="">
                        <TraineeDetails diffgr:id="TraineeDetails1" msdata:rowOrder="0">
                            <ID>40798297</ID>
                            <SELF_MANAGED>0</SELF_MANAGED>
                        </TraineeDetails>
                        <PersonDetails diffgr:id="PersonDetails1" msdata:rowOrder="0">
                            <ID>40798297</ID>
                            <FORENAMES>Alan Gibson</FORENAMES>
                            <FORENAME>Alan</FORENAME>
                            <SURNAME>Mordey</SURNAME>
                            <DOB>21/10/1945</DOB>
                            <EMPLOYER_NAME>Atkins</EMPLOYER_NAME>
                            <EMPLOYER_ADDRESS_1>The Axis</EMPLOYER_ADDRESS_1>
                            <EMPLOYER_ADDRESS_2>10 Holliday Street</EMPLOYER_ADDRESS_2>
                            <EMPLOYER_TOWN>BIRMINGHAM</EMPLOYER_TOWN>
                            <EMPLOYER_STATE>West Midlands</EMPLOYER_STATE>
                            <EMPLOYER_COUNTRY>UK</EMPLOYER_COUNTRY>
                            <EMPLOYER_POSTCODE>B1 1TF</EMPLOYER_POSTCODE>
                            <IPD_STATUS>0</IPD_STATUS>
                            <PAYMENT_RECEIVED>0</PAYMENT_RECEIVED>
                            <SM_PRODUCT_DESC>Mentor Support Training</SM_PRODUCT_DESC>
                            <SM_PRODUCT_PRICE>340.75</SM_PRODUCT_PRICE>
                            <ELIGIBLE_LEVEL>UNK</ELIGIBLE_LEVEL>
                            <ELIGIBLE_LEVEL_DESCRIPTION>Unknown</ELIGIBLE_LEVEL_DESCRIPTION>
                            <DEFAULT_LEVEL>ENGTECH</DEFAULT_LEVEL>
                            <DEFAULT_LEVEL_DESCRIPTION>EngTech</DEFAULT_LEVEL_DESCRIPTION>
                            <PERSON_AIM>CENG</PERSON_AIM>
                        </PersonDetails>
                    </NewDataSet>
                </diffgr:diffgram>
            </GetIPDTraineeDetailsResult>
        </GetIPDTraineeDetailsResponse>
    </soap:Body>
</soap:Envelope>

我想在我的架构中选择 xs:element TraineeDetails 并将数据作为值返回,即值的 IEnumerable,在本例中为 XElements 的 IEnumerable。这将带回这些值:

<TraineeDetails diffgr:id="TraineeDetails1" msdata:rowOrder="0">
    <ID>40798297</ID>
    <SELF_MANAGED>0</SELF_MANAGED>
</TraineeDetails>

有什么想法吗?看起来应该很简单,但是在选择后代时出现堆栈跟踪错误。

【问题讨论】:

  • 试试这个:var traineeDetails = doc.Descendants().Where(x => x.Name.LocalName == "element")
  • 请避免将基本上是文本的信息发布为图像。您可以很容易地将文本复制并粘贴到问题中 - 或者更好的是,生成一个 minimal 版本作为 minimal reproducible example 的一部分。
  • 另外,XML 并不是真正的数据,它只是架构...
  • @JonSkeet 我已经删除了图像并将其替换为 XML 字符串。
  • (叹气)不过,您并没有费心去格式化它,是吗?请更加尊重其他人的时间,并使用预览来检查结果是否像您想要的那样可读 如果您想帮助某人。我现在已经格式化了,但以后请自己格式化。现在,问题仍然存在,那就是架构,而不是实际的数据集。

标签: c# xml xmldocument


【解决方案1】:

您显示的 XML 中没有 xs 前缀的命名空间声明。您的 XML 文件是否有序,或者您是否缺少此文件?

xmlns:xs="http://www.w3.org/2001/XMLSchema"

如果没有,请确保在查询前缀元素时也添加命名空间:

XNamespace xs = "http://www.w3.org/2001/XMLSchema";
IEnumerable<XElement> elements = doc.Descendants(xs + "element");

【讨论】:

    【解决方案2】:

    根据这篇文章中的反馈,您可以使用它来选择后代并返回 XElements 的 IEnumerable:

    var traineeDetails = xDocument.Descendants("TraineeDetails");
    

    也可以在 C# 中使用 LINQ 来选择这些值,但我最终使用了选项 1:

    var traineeDetails = from c in doc.Descendants("TraineeDetails ") select c;
    

    【讨论】:

    • 嗯,既然from...select 基本上等同于var traineeDetails = doc.Descendants("TraineeDetails");,为什么还要使用它?我怀疑你最后也没有空间......
    • 另外,我认为代码不会选择您显示的 XML 中的元素,这基本上是架构,而不是实际数据。
    • @JonSkeet 我的错误,我已经用 XML 数据(不是 XML 的架构)更新了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多