使用LINQ to XML更改命名空间值的最简单方法是什么?

Tar*_*Tar 5 c# xml xaml serialization xml-namespaces

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

为什么?因为:

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

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

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

这是我的序列化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>
Run Code Online (Sandbox Code Playgroud)

(MyParagraph并且ParagraphMetaData是自定义类型,它们都存在于源程序集和目标程序MyParagraph集中.继承自WPFParagraph)

Tim*_* S. 6

这很容易做到.

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;
Run Code Online (Sandbox Code Playgroud)

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