Null возвращается при выборе узла в документе XML - PullRequest
1 голос
/ 10 июня 2009

Новое в XML. У меня есть сторонний веб-сервис, который предоставляет XML-документ, который я должен обновить значения элемента и передать обратно. Основная проблема заключается в том, что я получаю ошибку NullReferenceException при вызове метода node.RemoveAll () в приведенном ниже коде. Я вызываю метод RemoveAll (), потому что каждый элемент имеет атрибут xsi: nil, когда он предоставляется мне, и если я не удаляю его до обновления значения элемента, XML не будет проверяться веб-службой.

Документ XML, предоставленный сторонним веб-сервисом, выглядит следующим образом:

<?xml version="1.0" encoding="utf-16"?>
<TaskData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schema.sample.com/application/1/520800B">
  <Global>
    <RequestInfo xmlns="http://schema.sample.com/application/1/Types">
      <Requestor xsi:nil="true" />
      <Date_init xsi:nil="true" />
      <Shipto xsi:nil="true" />
      <Customer xsi:nil="true" />
      <Contact xsi:nil="true" />
      <Requestor_Email xsi:nil="true" />      
    </RequestInfo>    
   </Global>
  </TaskData>

Другие решения, которые я видел, использовали XmlNamespaceManager, но я не смог заставить его работать. Этот XML-документ имеет пространство имен, указанное для элемента TaskData, и другое пространство имен для элемента RequestInfo. Я попытался указать переменную XmlNamespaceManager для каждого пространства имен, но получил те же результаты .... при наведении курсора на переменную nsmgr в режиме прерывания обнаруживается, что «дочерние элементы не могут быть оценены» и что свойство DefaultNamespace является пустой строкой.

Public Sub testxml()

    Dim doc As New XmlDocument
    doc.Load("c:\temp\sample.xml")

    Dim nsmgr As XmlNamespaceManager = New XmlNamespaceManager(doc.NameTable)
    nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/520800B")

    Dim node As XmlNode = doc.SelectSingleNode("s:Requestor", nsmgr)
    node.RemoveAll()
    node.InnerText = "Your Name Goes Here"

    doc.Save("c:\temp\sample.xml")

End Sub

Ответы [ 4 ]

2 голосов
/ 10 июня 2009

Проблема с этим утверждением:

doc.SelectSingleNode("s:Requestor", nsmgr)

что вам нужно сделать, это

doc.SelectSingleNode("//s:Requestor",nsmgr)

"s: Requestor" означает дать мне узел под именем текущего узла s: Requester

"// s: Requestor" означает дать мне все узлы в документе с именем s: Requestor

если вы хотите игнорировать пространство имен, вы можете сделать

doc.SelectSingleNode("//*[local-name()='Requestor']")
0 голосов
/ 12 июня 2009

Вы должны иметь возможность отказаться от любых вызовов пространства имен в вашем вызове выбора, я все равно предпочитаю циклически просматривать мой документ ... но это только я.

0 голосов
/ 10 июня 2009

В вашем коде есть две ошибки. Одним из них является XPath, используемый для выбора узла (как указал Грег). Второе - это пространство имен. Возможно, я ошибаюсь, но при интерпретации XML-документа элемент TaskData имеет следующее объявление пространства имен:

xmlns="http://schema.sample.com/application/1/520800B"

... который устанавливает пространство имен для элементов без префиксов.

Но тогда тег RequestInfo имеет следующее объявление пространства имен:

xmlns="http://schema.sample.com/application/1/Types"

Таким образом, внутри тега RequestInfo есть другое пространство имен для тегов без префиксов. В вашем коде вы используете первое из этих двух пространств имен для соответствия тегу, который находится во втором, что не сработает. Есть два способа решить это. Одним из них является просто изменить пространство имен в вашем коде:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/Types");
XmlNode node = doc.SelectSingleNode("//s:Requestor", nsmgr);

Второй - определить оба пространства имен и использовать выражение XPath, указывающее полный путь к тегу:

XmlNamespaceManager nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("r", "http://schema.sample.com/application/1/520800B");
nsmgr.AddNamespace("s", "http://schema.sample.com/application/1/Types");
XmlNode node = doc.SelectSingleNode(@"/r:TaskData/r:Global/s:RequestInfo/s:Requestor", nsmgr);

Оба эти случая приводят к одному и тому же результату; node не null.

0 голосов
/ 10 июня 2009

Я не уверен, правильно ли я понял вашу задачу. Но если вам нужно просто удалить часть xsi: nil = "true", почему бы вам не загрузить ее как строку и не вызвать

string.replace("xsi:nil=\"true\"", "")

Конечно, это не самое чистое решение, но я еще не знаком с API обработки XML C #, поэтому мне придется обратиться к MSDN, чтобы привыкнуть. Возможно, это уже решает вашу проблему.

...