Добавление атрибута пространства имен в XElement - как предотвратить пустое / пустое пространство имен на дочерних элементах?
Мне нужно прочитать 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 ответ
Удалить Elements
от твоего For
цикл, он также вызывал обработку всех дочерних элементов.
For Each elem In xmlDoc.Descendants("Itinerary") ''//.Elements
elem.Name = ns + elem.Name.LocalName
Next
РЕДАКТИРОВАТЬ
Извините, это не сработало, как вы заметили, у меня еще не было кофе.
Причина, по которой это делает.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>