ما هي الطريقة الجيدة للعثور على قيمة محددة في مستند XML باستخدام C#؟

StackOverflow https://stackoverflow.com/questions/374734

  •  22-08-2019
  •  | 
  •  

سؤال

أقوم بالاتصال بخدمة WebService التي كشفت عنها Oracle والتي تقبل إدخال ItemID وترجع لي رقم العنصر المقابل.أريد الحصول على رقم العنصر الذي تم إرجاعه من ملف XML الموجود في الرد.

يبدو ملف XML كما يلي:

<env:Envelope
  xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:ns0="http://dev1/MyWebService1.wsdl">
 <env:Header>
  <wsse:Security
    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
    env:mustUnderstand="1"/>
 </env:Header>
 <env:Body>
  <ns0:getItemNbrByItemIdResponseElement>
   <ns0:result>1010603</ns0:result>
  </ns0:getItemNbrByItemIdResponseElement>
 </env:Body>
</env:Envelope>

أنا مهتم بالاستيلاء على فقط <ns0:result>1010603</ns0:result> وخاصة فقط 1010603.

لم أقم بالكثير من العمل في تحليل XML باستخدام C# وأنا أتلاعب ببعض الطرق المختلفة حتى الآن.ما هي الطريقة الموصى بها للقيام بذلك؟

أنا على VS2008 (لذا فإن XPath متاح وما إلى ذلك)

هل كانت مفيدة؟

المحلول

ويهمني شخصيا استخدام LINQ إلى XML، لأنني وجدت أن أسهل للتعامل مع من كسباث، لا سيما عندما يتعلق الأمر بمساحات. كنت تفعل شيئا مثل:

XNamespace ns0 = "http://dev1/MyWebService1.wsdl";

String result = doc.Descendants(ns0 + "result").First().Value;

ويتوقع أن يكون لاحظ أن doc هنا ل XDocument ، لا XmlDocument . (تخميني هو أن هذا هو السبب في أنه لم تظهر لك.)

نصائح أخرى

وFWIW يمكنك خداع القضية مساحة الاسم مع كسباث مثل هذا: //*[local-name()='result']

إذا كنت لا تريد أن تذهب لينق هل يمكن استخدام XPathDocument لاسترداد قيمة:

XPathDocument xmldoc = new XPathDocument(@"C:\tmp\sample.xml");
XPathNavigator nav = xmldoc.CreateNavigator();

XmlNamespaceManager nsMgr = new XmlNamespaceManager(nav.NameTable);
nsMgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");

XPathNavigator result = nav.SelectSingleNode("//ns0:result", nsMgr);
System.Diagnostics.Debug.WriteLine(result.Value);

وXPathDocument لديه أقل أثر الذاكرة وعلى الأرجح أسرع في السيناريو الخاص بك من XmlDocument. XmlDocument يبني نموذج الكائن الكامل من وثيقة XML الخاصة بك في الذاكرة في حين XPathDocument لا تفعل ذلك.

ومن على قمة رأسي، يجب أن تعمل ما يلي:

XmlDocument doc = new XmlDocument();
doc.PreserveWhitespace = true;

XmlNamespaceManager mgr = GetNamespace(doc);
doc.LoadXml(xmltext);

XmlNode nd = doc.DocumentElement.SelectSingleNode("//ns0:result", mgr);

وكود مساحة الاسم يبدو مثل هذا:

private XmlNamespaceManager GetNamespace(XmlDocument document)
{
    XmlNamespaceManager mgr = new XmlNamespaceManager(document.NameTable);
    mgr.AddNamespace("ns0", "http://dev1/MyWebService1.wsdl");
    return mgr;
}

وتحتاج إلى استخدام مدير مساحة الاسم لأن المستند XML ديها مساحة الأسماء المرتبطة به، و XPath يستخدم هذا في القرار الاستعلام.

لحل هذه المشكلة، استخدمت إجابة جون سكيت.إليك الكود الذي كان عليّ تنفيذه لإنجاز هذا العمل (لمنفعة أي شخص آخر في المستقبل).

XmlDocument xmlDoc = new XmlDocument();

XNamespace ns0 = "http://dev1/MyWebService1.wsdl";

xmlDoc.Load(request.GetResponse().GetResponseStream());

XDocument xDoc = XDocument.Load(new XmlNodeReader(xmlDoc));                          

String result = xDoc.Descendants(ns0 + "result").First().Value;

يفترض هذا بالطبع أنني أتلقى ردي من طلب HttpWebRequest المسمى طلب.

هناك إجابات جيدة جدًا وكاملة على هذا السؤال.

أود أن أضيف فقط من باب الفضول، أن تعبير XPath البسيط للغاية يقوم بهذه المهمة في هذه الحالة بالذات:

    normalize-space(/)

يتم ذلك بسهولة في C# باستخدام شيء مثل السطرين أدناه:

        XPathNavigator navigator = document.CreateNavigator();

        string res = (string)navigator.Evaluate("normalize-space(/)");

ومع التحسين الجيد لمحرك .NET XPath، قد يكون تقييمه فعالاً.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top