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)
。我想在另一个项目中将这个GUI外观可视化到其他地方(使用System.Windows.Markup.XamlReader.Parse(raw)
进行反序列化)。
我不想链接到原始程序集!
我只需要更改命名空间,因此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>
(MyParagraph
和ParagraphMetaData
是自定义类型,它们都存在于源程序集和目标程序集中。MyParagraph
继承WPF
的{{1}})
答案 0 :(得分: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;
这两个部分都需要导致XAML正确且易于阅读,因为元素的名称空间与xmlns
中的XDocument
声明分开存储。如果您只更改“gcs”的含义,那么它将编写xmlns
语句以将元素保留在旧的命名空间中。如果您只更改元素所在的命名空间,那么它将根据需要包含xmlns="clr-namespace:NsTwo;assembly=AsmTwo"
个语句,并忽略gcs
(它仍会引用旧的NsOne
)。