将命名空间属性添加到XElement - 如何防止子元素上的空/空命名空间?

时间:2011-03-17 11:29:44

标签: vb.net linq-to-xml xml-namespaces 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>

但是当我运行以下代码将命名空间应用于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 个答案:

答案 0 :(得分: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命名空间中,{ {1}}与<SegmentFlight>位于empty名称空间中。如果您希望<Itinerary>成为与<SegmentFlight>相同的名称空间的一部分,那么您需要递归地应用名称空间。当您致电<Segments> .Net将输出您期望的内容。这是一个递归版本:

ToString()

输出:

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