【问题标题】:What's the easiest method to change the namespace value using LINQ to XML?使用 LINQ to XML 更改命名空间值的最简单方法是什么?
【发布时间】:2013-12-30 15:32:59
【问题描述】:

TL/DR:使用LINQ to XML 更改命名空间值的最简单方法是什么,例如从xmlns:gcs="clr-namespace:NsOne;assembly=AsmOne"xmlns:gcs="clr-namespace:NsTwo;assembly=AsmTwo"

为什么?因为:

我使用System.Windows.Markup.XamlWriter.Save(myControl) 序列化了Xaml。我想在另一个项目中将这个 GUI 外观可视化(使用 System.Windows.Markup.XamlReader.Parse(raw) 反序列化)。

我不想链接到原始程序集!

我只需要更改命名空间,所以XamlReader.Parse(raw) 不会抛出异常。我目前使用正则表达式它可以工作,但我不喜欢这种方法(例如,如果我在CDATA 中有xmlns:gcs="clr-namespace:NsOne;assembly=AsmOne"

这是我的序列化Xaml

<FlowDocument PagePadding="5,0,5,0" AllowDrop="True"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:gcs="clr-namespace:NsOne;assembly=AsmOne"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <gcs:MyParagraph Margin="0,0,0,0">
        <gcs:MyParagraph.MetaData>
            <gcs:ParagraphMetaData UpdaterParagraphUniqueId="1" />
        </gcs:MyParagraph.MetaData>
        <Span>some text...</Span>
    </gcs:MyParagraph>
    <gcs:MyParagraph Margin="0,0,0,0" Background="#FFF0F0F0">
        <gcs:MyParagraph.MetaData>
            <gcs:ParagraphMetaData UpdaterParagraphUniqueId="2" />
        </gcs:MyParagraph.MetaData>
        <Span Foreground="#FF0000FF">some more text...</Span>
    </gcs:MyParagraph>
</FlowDocument>

MyParagraphParagraphMetaData 是自定义类型,它们都存在于源程序集和目标程序集中。MyParagraph 继承了WPFParagraph

【问题讨论】:

    标签: c# xml xaml serialization xml-namespaces


    【解决方案1】:

    这很容易做到。

    var doc = XDocument.Parse(raw);
    XNamespace fromNs = "clr-namespace:NsOne;assembly=AsmOne";
    XNamespace toNs = "clr-namespace:NsTwo;assembly=AsmTwo";
    
    // redefines "gcs", but doesn't change what namespace the elements are in
    doc.Root.SetAttributeValue(XNamespace.Xmlns + "gcs", toNs);
    
    // this actually changes the namespaces of the elements from the old to the new
    foreach (var element in doc.Root.Descendants()
                                      .Where(x => x.Name.Namespace == fromNs))
        element.Name = toNs + element.Name.LocalName;
    

    这两个部分都是正确且易于阅读的 XAML 所必需的,因为元素的命名空间与 XDocument 中的 xmlns 声明分开存储。如果您仅更改“gcs”的含义,那么它将编写xmlns 语句以将元素保留在其旧名称空间中。如果您只更改元素所在的命名空间,那么它将根据需要包含xmlns="clr-namespace:NsTwo;assembly=AsmTwo" 语句,并忽略gcs(仍将引用旧的NsOne)。

    【讨论】:

      猜你喜欢
      • 2011-01-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多