Добавление атрибута пространства имен в XElement - как предотвратить пустое / пустое пространство имен на дочерних элементах? - PullRequest
2 голосов
/ 17 марта 2011

Мне нужно прочитать документ XML из записи базы данных в объект XDocument, чтобы его можно было десериализовать.Чтобы десериализация работала, мне нужно применить определенное пространство имен к каждому из элементов уровня 1.Так что XML выглядит примерно так:

<Itinerary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Segments>
        <SegmentFlight>
        </SegmentFlight>
        <!-- more child elements -->
    </Segments>
    <References>
        <!-- child elements -->
    </References>
    <Fares>
        <!-- child elements -->
    </Fares>
</Itinerary>

И мне нужно, чтобы он выглядел так:

<Itinerary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Segments xmlns="http://myurl">
        <SegmentFlight>
        </SegmentFlight>
        <!-- more child elements -->
    </Segments>
    <References xmlns="http://myurl">
        <!-- child elements -->
    </References>
    <Fares xmlns="http://myurl">
        <!-- child elements -->
    </Fares>
</Itinerary>

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

Dim xmlDoc As XDocument = XDocument.Load(New System.IO.StringReader(xmlStringFromDB))
Dim ns As XNamespace = "http://myurl"

For Each elem In xmlDoc.Descendants("Itinerary").Elements
    elem.Name = ns + elem.Name.LocalName
Next    

Я получаю пустой атрибут пространства имен xmln = "" для каждого дочернего элемента в этом элементе, что приводит к сбою десериализации:

<Itinerary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <Segments xmlns="http://myurl">
        <SegmentFlight xmlns="">
            <!-- etc ... -->
        </Segments>

Как предотвратить добавление пустого / пустого пространства имен к каждому дочернему элементу элемента, к которому применено требуемое пространство имен?

1 Ответ

1 голос
/ 17 марта 2011

Удалите Elements из цикла For, это также приводило к обработке всех дочерних элементов.

    For Each elem In xmlDoc.Descendants("Itinerary") ''//.Elements
        elem.Name = ns + elem.Name.LocalName
    Next

EDIT

Извините, это не сработало, как вы заметили, у меня еще не было кофе.

Причина, по которой это делается в .Net, заключается в том, что вы сбрасываете пространство имен по умолчанию в середине документа. Если бы оно не добавляло пустое пространство имен к дочерним элементам, тогда все дочерние элементы <Segments> автоматически были бы частью пространства имен http://myurl. Может быть, это тот результат, который вы хотите, но, поскольку вы не сказали .Net, что вы предполагаете, что нет.

Чтобы сказать, что по-другому, вывод, который вы получаете, говорит, что <Itinerary> находится в пространстве имен empty, <Segments> находится в пространстве имен http://myurl и <SegmentFlight> находится в том же empty Пространство имен как <Itinerary>. Если вы хотите, чтобы <SegmentFlight> был частью того же пространства имен, что и <Segments>, то вам нужно рекурсивно применить пространство имен. Когда вы звоните ToString() .Net будет выводить то, что вы ожидаете. Вот рекурсивная версия:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    Dim xmlDoc As XDocument = XDocument.Load(New System.IO.StringReader(xmlStringFromDB))

    Dim ns As XNamespace = "http://myurl"
    ApplyNameSpaceToAllChildren(xmlDoc.Descendants("Itinerary").Elements(), ns)

    Trace.WriteLine(xmlDoc.ToString())
End Sub
Private Sub ApplyNameSpaceToAllChildren(ByVal elements As IEnumerable(Of XElement), ByVal ns As XNamespace)
    For Each elem In elements
        elem.Name = ns + elem.Name.LocalName
        If elem.HasElements Then
            ApplyNameSpaceToAllChildren(elem.Elements, ns)
        End If
    Next
End Sub

Это выводит:

<Itinerary xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Segments xmlns="http://myurl">
    <SegmentFlight></SegmentFlight>
    <!-- more child elements -->
  </Segments>
  <References xmlns="http://myurl">
    <!-- child elements -->
  </References>
  <Fares xmlns="http://myurl">
    <!-- child elements -->
  </Fares>
</Itinerary>
...