Мне нужно изменить XML-файл (фактически файл отчета .rdlc) и добавить некоторые узлы, которые имеют много дочерних узлов (и эти дочерние узлы снова имеют дочерние узлы). На самом деле они почти такие же, как этот:
<TablixRow>
<Height>0.23622in</Height>
<TablixCells>
<TablixCell>
<CellContents>
<Textbox Name="Textbox1">
<CanGrow>true</CanGrow>
<KeepTogether>true</KeepTogether>
<Paragraphs>
<Paragraph>
<TextRuns>
<TextRun>
<Value/>
<Style/>
</TextRun>
</TextRuns>
<Style/>
</Paragraph>
</Paragraphs>
<rd:DefaultName>Textbox1</rd:DefaultName>
<Style>
<Border>
<Style>None</Style>
</Border>
<PaddingLeft>2pt</PaddingLeft>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
<PaddingBottom>2pt</PaddingBottom>
</Style>
</Textbox>
</CellContents>
</TablixCell>
<TablixCell>
<CellContents>
<Textbox Name="Textbox5">
<CanGrow>true</CanGrow>
<KeepTogether>true</KeepTogether>
<Paragraphs>
<Paragraph>
<TextRuns>
<TextRun>
<Value/>
<Style/>
</TextRun>
</TextRuns>
<Style/>
</Paragraph>
</Paragraphs>
<rd:DefaultName>Textbox5</rd:DefaultName>
<Style>
<Border>
<Style>None</Style>
</Border>
<PaddingLeft>2pt</PaddingLeft>
<PaddingRight>2pt</PaddingRight>
<PaddingTop>2pt</PaddingTop>
<PaddingBottom>2pt</PaddingBottom>
</Style>
</Textbox>
</CellContents>
</TablixCell>
</TablixCells>
</TablixRow>
Так какой самый простой способ сделать это? В обычном случае я просто создаю XmlNode и некоторые объекты XmlAttribute, присоединяю эти атрибуты к узлу и таким же образом создаю дочерние узлы и, наконец, добавляю каждый дочерний узел в его родительский. Само собой разумеется, это будет утомительно обрабатывать мой пример узла. Есть ли более простой способ сделать это? Как и в случае с классом XmlDocument, есть функция LoadXml (xml как строка), которая принимает строку как весь xml-файл и создает структуру. Есть ли подобный способ создания объекта XmlNode? Так что мне нужно только предоставить весь фрагмент строки, представляющий мой узел, а затем перейти к дочернему узлу, для которого мне нужно изменить значение. Спасибо!
Обновление:
Я использую VB.NET. И есть одна проблема с пространством имен при использовании XElement. По этой ссылке
XName Class , он говорит, что для C # рекомендуется просто использовать переопределенный оператор add для объединения элемента и NS, но для VB он рекомендует использовать импорт сверху (в примере вне модуля. Я полагаю, это также должно работать для класса), и тогда все будут использовать этот NS автоматически. Однако, это не так. Например, если я дам
Dim para As XElement = _
<ReportParameter Name="HasErr">
<DataType>Boolean</DataType>
<DefaultValue>
<Values>
<Value>False</Value>
</Values>
</DefaultValue>
<Prompt>ReportParameter1</Prompt>
</ReportParameter>
он автоматически присоединит мой указанный (и указанный по умолчанию) NS. Но если я использую XElement.Parse (xml As String), где xml - это та же самая строка, представляющая xml, он вообще не добавит этот NS, что в итоге будет использовать пустой NS (причина, по которой я хочу использовать XElement. Parse - я хочу указать там значение моего настраиваемого параметра, например & MY_TYPE_NAME &).
Вторая проблема - при использовании кода @JohnD я пытаюсь
xdoc.Root.Elements("ReportParameters").FirstOrDefault()
, который, как я предполагаю, также будет использовать мой объявленный и заданный по умолчанию NS, ничего не вернет, то есть он ищет в пустом пространстве имен, но на самом деле он находится в упомянутом NS.
Кто-нибудь знает, по какой причине MS сделала так, что не существует конструктора для класса XName, где я могу указать пространство имен, прежде чем использовать его? Он говорит, что существует только одно неявное преобразование, поэтому, когда ему дается строка, представляющая имя элемента в
xdoc.Root.Elements("ReportParameters")
неявно генерирует один объект XName для индексации поиска в Elements. Но это действительно неуклюже.
Последнее обновление:
Теперь я нашел решение для решения своей первой проблемы в своем обновлении: теперь я использую XML Literals для создания XElement, и в нем можно использовать выражения. Итак, теперь это выглядит так:
Dim paraDefNode As XElement = _
<ReportParameter Name=<%= para.Value %>>
<DataType>String</DataType>
<DefaultValue>
<Values>
<Value>False</Value>
</Values>
</DefaultValue>
<Prompt>ReportParameter1</Prompt>
</ReportParameter>
и он добавит мой указанный NS. (как я уже сказал, XElement.Parse (string) не добавит его). Теперь я могу построить правильный узел. Что касается моей второй проблемы, я все еще не могу понять: я не могу перейти к целевому узлу, используя имя элемента, так как он не будет искать правильный NS.
В любом случае я отмечу пост @JohnD как ответ, поскольку он предложил использовать LINQ to XML.