使用 LINQ to XML 更改命名空间值的最简单方法是什么? [英] What's the easiest method to change the namespace value using LINQ to XML?

查看:30
本文介绍了使用 LINQ to XML 更改命名空间值的最简单方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

TL/DR: What's the easiest method to change the namespace value using LINQ to XML, say from xmlns:gcs="clr-namespace:NsOne;assembly=AsmOne" to xmlns:gcs="clr-namespace:NsTwo;assembly=AsmTwo"?

为什么?因为:

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

I serialized Xaml using System.Windows.Markup.XamlWriter.Save(myControl). I want to visualize this GUI appearance somewhere else (deserializing using System.Windows.Markup.XamlReader.Parse(raw)), in another project.

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

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

I just need to change the namespace, so XamlReader.Parse(raw) won't throw an exception. I currently do it using regular-expressions and it works, but I don't like that method (e.g. if I have xmlns:gcs="clr-namespace:NsOne;assembly=AsmOne" inside a 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>

(MyParagraphParagraphMetaData 是自定义类型,它们都存在于源程序集和目标程序集中.MyParagraph 继承了 WPF段落)

(MyParagraph and ParagraphMetaData are custom types and they both exist at the source assembly and the destination assembly. MyParagraph inherits WPF's Paragraph)

推荐答案

这很容易做到.

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).

Both portions are needed to result in XAML that's both correct and easily-readable, because the namespace of the elements is stored separately from the xmlns declarations in an XDocument. If you only change what "gcs" means, then it will write xmlns statements to keep the elements in their old namespace. If you only change what namespace the elements are in, then it will include xmlns="clr-namespace:NsTwo;assembly=AsmTwo" statements as necessary, and ignore gcs (which will still reference the old NsOne).

这篇关于使用 LINQ to XML 更改命名空间值的最简单方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆