XElement.Add(XElement)会自动将命名空间添加到子节点吗?

时间:2011-11-04 00:13:54

标签: vb.net xml-namespaces linq-to-xml xelement

我正在使用XElement来操作我的xml文件:找到目标节点,然后向其添加子节点。但现在我有一个问题。假设我的xml文件如下所示:

<Report xmlns="MY_NAMESPACE"
  <Width>100</Width>
  <Height>100</Height>
  <ReportItems>
    <ReportItem>
...
</Report>

我想使用VB.NET向<ReportItem>节点添加新的<ReportItems>。在这个链接How to: Create a Document with Namespaces (LINQ to XML) (Visual Basic)中,它表示为了声明和使用命名空间,它需要在文件的开头导入它们(它与C#用法不同)。所以我做Imports <xmlns="MY_NAMESPACE">。现在我需要1)首先找到<ReportItems>节点,然后2)添加我的新节点。为了做第一步,我尝试了

Dim xmldoc = XDocument.Load(MY_XML_FILE_PATH)
Dim target = xmldoc.Root.Elements("{MY_NAMESPACE}" & "ReportItems").FirstOrDefault

要做第2步),我做了

Dim newNode As XElement = _
    <ReportItem/>
target.Add(newNode)

现在有问题:如果我在查询Root元素时没有指定"{MY_NAMESPACE}",我根本找不到ReportItems。这是因为字符串实际上用于隐式构造XName对象(上帝知道为什么我不能显式地将NS分配给XName对象),并且该对象用于搜索。如果我不给出花括号部分,它将在空命名空间内搜索,因此它找不到MY_NAMESPACE中的<ReportItems>节点。但是,如果我给出这个大括号命名空间,最终的xml文件将如下所示:

<Report xmlns="MY_NAMESPACE"
  <Width>100</Width>
  <Height>100</Height>
  <ReportItems>
    <ReportItem>
    <ReportItem xmlns="MY_NAMESPACE">    
...
</Report>

第二个<ReportItem>是新添加的,但遗憾的是这不是一个有效的文件(我的解析器在进一步处理xml文件时抱怨)。那么如何让这个新项目看起来与现有项目完全一样,没有任何命名空间?这让我发疯了。我花了一整天的时间才弄清楚我需要添加花括号以便找到目标节点(它不像上面的链接那样自动添加并自动搜索默认的NS),但是现在它添加不必要的东西这一定是开玩笑吧!

1 个答案:

答案 0 :(得分:2)

我遇到了类似的问题,我的解决方案是在保存Xml时省略重复的命名空间:

Dim sb As New StringBuilder()
Dim settings As XmlWriterSettings = New XmlWriterSettings()
settings.NamespaceHandling = NamespaceHandling.OmitDuplicates

Using writer As XmlWriter = XmlWriter.Create(sb, settings)
    Dim xdoc As XDocument = WriteDocument()
    xdoc.Save(writer)
End Using

您也可以使用具有OmitDuplicates的SaveOptions参数调用XDocument.Save。