1

在 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<string> 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

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

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

-干杯

4

1 回答 1

0

我终于找到了解决这个问题的方法,它可能不是最好的方法,但它是可靠的。从我尝试查询节点时所看到的内容来看,该元素将被定位但它不会更新我认为这部分是由于我尝试.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() 等

在这个片段中,我选择了节点,删除了所有子元素,然后注入了一个新结构

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();

我有兴趣看到其他建议或想法。

谢谢

于 2013-08-21T15:49:25.660 回答