XElement.Add (XElement) автоматически добавляет пространство имен в дочерний узел? - PullRequest
0 голосов
/ 04 ноября 2011

Я использую XElement для манипулирования моим XML-файлом: чтобы найти целевой узел, а затем добавить к нему дочерний узел. Но сейчас у меня есть одна проблема. Допустим, мой xml-файл выглядит так:

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

И я хочу добавить новый <ReportItem> к узлу <ReportItems>, используя VB.NET. В этой ссылке Как: создать документ с пространствами имен (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)

Теперь возникает проблема: если я не укажу "{MY_NAMESPACE}" при запросе элемента Root, я вообще не смогу найти ReportItems. Это потому, что строка на самом деле используется для неявного создания объекта XName (бог знает, почему я не могу явно назначить NS объекту XName), и этот объект используется для поиска. Если я не укажу фигурные скобки, он будет искать в пустом пространстве имен, поэтому не может найти узел <ReportItems>, который находится в MY_NAMESPACE. Но если я дам это пространство имен в фигурных скобках, окончательный XML-файл будет выглядеть так:

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

Второй <ReportItem> является вновь добавленным, но, к сожалению, это недопустимый файл (мой анализатор жалуется на дальнейшую обработку XML-файла). Итак, как я могу сделать этот новый элемент похожим на существующий без какого-либо пространства имен? Это сводит меня с ума. Я потратил целый день, чтобы понять, что мне нужно добавить фигурные скобки, чтобы он нашел целевой узел (он не работает так, как в приведенной выше ссылке, что он добавляет и ищет NS по умолчанию автоматически), но теперь он добавляет что-то ненужное? Это должно быть шутишь!

1 Ответ

2 голосов
/ 22 марта 2012

У меня была похожая проблема, и я решил исключить дублирующиеся пространства имен при сохранении 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

Вы также можете вызвать XDocument.Save с параметрами SaveOptions, которые также имеют OmitDuplicates.

...