【问题标题】:.ReplaceWith() not replacing XElement.ReplaceWith() 不替换 XElement
【发布时间】:2013-08-09 15:29:35
【问题描述】:

在一个 xml 文档中,我有以下内容

  ...  
    <TablixMembers>
       <TablixMember>
          <Group Name="Details" />
       </TablixMember>
     </TablixMembers>
   </TablixMember>
     <TablixHeader Name="MyField3" />
     <TablixHeader Name="MyField2" /> 
 </TablixMembers>
</TablixMember>

我有一个 for 循环,它使用字段名称 ("MyField3, MyField2, ...) 查找每个元素

for (int g = 0; g < remainingtotals; g++)
{
   groupTotals.Reverse();
   ff.Add(new XElement(ns + "TablixHeader"));
   ff.Descendants(ns + "TablixHeader").Last().SetAttributeValue("Name", groupTotals[g]);

   string nName = GenerateUniqueName("Nsted");
   while (ff.Descendants(ns + "TablixHeader").Any(n => (string)n.Attribute("Name") == groupTotals[g]))
   {
     var newnode = ff.Descendants(ns + "TablixHeader").Where(n => (string)n.Attribute("Name") == groupTotals[g]).Single();
     newnode.ReplaceWith(new XElement(tGroupHeader));
   }

groupTotals.Reverse();
} 

在这个循环中,我有一个List&lt;string&gt; groupTotals,它保存着字段的名称。 它可能不需要在 while 循环中(我添加这个是为了测试)我有一个查询来查找特定字段

var newnode = ff.Descendants(ns + "TablixHeader").Where(n => (string)n.Attribute("Name") == groupTotals[g]).Single();
         newnode.ReplaceWith(new XElement(tGroupHeader));

这设置 newnode 等于:

<TablixHeader Name="MyField3" xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition" />

在下一行我试图用一个新的 xml 元素结构替换这个节点

newnode.ReplaceWith(new XElement(tGroupHeader));

tGroupHeader 是一个内存流,其中包含一个大型 xml 元素模板,应插入并替换所选属性名称的当前 tablix 节点。

当此代码运行时,节点不会被替换。实际上什么都没有发生,我在节点上设置了断点,没有引发 xml 异常,它只是直接通过它。我假设我要么不正确地调用该方法,要么选择单个节点是导致它不替换元素的原因。

我还认为这可能是由于注入了一个大型 xml 结构,但我也只使用一个元素进行了测试,例如:

newnode.ReplaceWith(new XElement(ns + "Size"));// ns is the xml namespace for the schema I am using

这也没有导致元素被替换。

谁能提供一些关于我可能做错了什么的见解?

-干杯

【问题讨论】:

  • 更安全然后抱歉:您在修改文档后是否致电XDocument.Save()
  • 文档被渲染/创建,只是使用 ReplaceWith 不会用新的 xml 替换当前节点
  • 你解决了吗,我遇到了类似的问题

标签: c# linq linq-to-xml


【解决方案1】:

我终于找到了解决这个问题的方法,它可能不是最好的方法,但它是可靠的。从我尝试查询节点时可以看到该元素将被定位但它不会更新我认为这部分是由于我尝试在一个方法中基于.Descendants() 查询进行注入和更新(这可能不正确,但这是我能确定的全部)。

我使用的解决方法不是在创建元素时尝试导航元素的 xml 结构,而是添加了一个具有特定名称的 ID 属性。

ff.Add(new XElement(ns + "TablixMember"));
ff.Descendants(ns + "TablixMember").Last().SetAttributeValue("Name", groupTotals[g]);
ff.Descendants(ns + "TablixMember").Last().SetAttributeValue("ID", groupedItemTotals[g].GroupPosition.ToString());

这将插入一个 XElement,例如

   <TablixMembers>
      <TablixMember>
        <TablixHeader xmlns="http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition">
         <Size>1in</Size>
            <CellContents>
              <Textbox Name="GroupTotalPPPccc2973356bf4beaa92cb0409b37b8ef" ID="1">
                   <CanGrow>true</CanGrow>
                       <KeepTogether>true</KeepTogether>
<--end snip -->

添加 id 后,查询节点变得更加简单

  var newnode = ff.Descendants(ns + "TablixMember").Where(n => (string)n.Attribute("ID") == groupedItemTotals[g].GroupPosition.ToString()).Single();

然后我可以从这里使用 Replace() 更新节点内的元素。 ReplaceWith() SetAttribut() 等

在这个sn-p中我选择了节点,移除了所有的子元素,然后注入了一个新的结构

newnode.RemoveAll();
newnode.Add(new XElement(tGroupHeader),
new XElement(ns + "KeepWithGroup"));
newnode.Descendants(ns + "TablixHeader").Last().Descendants(ns + "Textbox").Last().SetAttributeValue("Name", nName);

最后,由于我使用的当前架构不支持 ID 属性,因此我进行了一些清理以删除任何不受支持的属性。

report.Descendants(ns + "TablixMember").Where(p => (string)p.Attribute("ID") != null).Attributes("ID").Remove();
report.Descendants(ns + "Textbox").Where(p => (string)p.Attribute("ID") != null).Attributes("ID").Remove();

我有兴趣了解其他建议或想法。

谢谢

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 2012-01-24
    • 1970-01-01
    • 1970-01-01
    • 2016-08-16
    相关资源
    最近更新 更多