我需要修改一个 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 as string),它将一个字符串作为整个 xml 文件并构造结构。有没有类似的方法来构造一个 XmlNode 对象?这样我只需要提供代表我的节点的整个字符串,然后导航到我需要更改值的子节点。谢谢!
更新:我正在使用 VB.NET。使用 XElement 时命名空间存在一个问题。在此链接 XName Class中,它说对于 C#,建议仅使用覆盖的 add 运算符来组合元素和 NS,但对于 VB,它建议在顶部使用 Import(在模块外部的示例中。我认为它也应该为 Class 工作)然后一切都会自动使用这个 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.解析是我想在那里提供我的自定义参数值,例如 & 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。