我正在使用Linq to XML来创建一个新的XML文件。我从现有的XML文件中获取文件的某些部分。我使用以下代码。
var v2 = new XDocument(
new XDeclaration("1.0", "utf-16", ""),
new XComment(string.Format("Converted from version 1. Date: {0}", DateTime.Now)),
new XElement(ns + "keyem",
new XAttribute(XNamespace.Xmlns + "xsd", xsd.NamespaceName),
new XAttribute(XNamespace.Xmlns + "xsi", xsi.NamespaceName),
new XAttribute(xsi + "schemaLocation", schemaLocation.NamespaceName),
new XAttribute("version", "2"),
new XAttribute("description", description),
new XElement(ns + "layout",
new XAttribute("type", type),
new XAttribute("height", height),
new XAttribute("width", width),
settings.Root) // XML from an existing file
问题是它添加了xmlns =“”现有文件中的第一个元素。
结果是:
<?xml version="1.0" encoding="utf-16"?>
<foo
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://tempuri.org/KeyEmFileSchema.xsd KeyEmFileSchema.xsd"
xmlns="http://tempuri.org/KeyEmFileSchema.xsd">
<settings xmlns="">
...
</settings>
</foo>
我正在阅读的XML文件看起来像这样,但我可以根据需要进行更改
<?xml version="1.0" encoding="utf-16"?>
<settings>
<colormaps>
<colormap color="Gray" textcolor="Black"/>
<colormap color="DarkGray" textcolor="White"/>
<colormap color="Black" textcolor="White"/>
<colormap color="Cyan" textcolor="Black"/>
</colormaps>
<macromaps>
<macromap pattern="^@([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{ESC}$1{ESC}$2{MOUSERESET}"/>
<macromap pattern="^\$([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1{ESC}$2{MOUSERESET}"/>
<macromap pattern="^\$([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1"/>
</macromaps>
<keydefault color="Cyan"/>
<groupdefault color="DarkGray"/>
</settings>
答案 0 :(得分:12)
您看到了这一点,因为settings元素(可能来自您的文档)不在此命名空间中。它位于默认的/ null-uri名称空间中。
您需要转换输入文档才能更改其命名空间。
这个稍微简化的示例将您的xml文件放入另一个文档中,但在此之前,它会将该xml文件中每个元素的名称空间更改为目标文档的名称空间...
static void ProcessXmlFile()
{
XNamespace ns = "http://tempuri.org/KeyEmFileSchema.xsd/";
// load the xml document
XElement settings = XElement.Load("data.xml");
// shift ALL elements in the settings document into the target namespace
foreach (XElement e in settings.DescendantsAndSelf())
{
e.Name = ns + e.Name.LocalName;
}
// write the output document
var file = new XDocument(new XElement(ns + "foo",
settings));
Console.Write(file.ToString());
}
结果......
<foo xmlns="http://tempuri.org/KeyEmFileSchema.xsd/">
<settings>
<colormaps>
<colormap color="Gray" textcolor="Black" />
<colormap color="DarkGray" textcolor="White" />
<colormap color="Black" textcolor="White" />
<colormap color="Cyan" textcolor="Black" />
</colormaps>
<macromaps>
<macromap pattern="^@([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{ESC}$1{ESC}$2{MOUSERESET}" />
<macromap pattern="^\$([0-9A-F]{2})\|([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1{ESC}$2{MOUSERESET}" />
<macromap pattern="^\$([0-9A-F]{2})$" replace="{USERCLICK}{ESC}$1" />
</macromaps>
<keydefault color="Cyan" />
<groupdefault color="DarkGray" />
</settings>
</foo>
如您所见,settings元素现在与foo元素位于同一名称空间中。这本质上是一个快速而又脏的xml转换,显然它不尊重您导入的xml doc中的任何名称空间。但这可能是你所追求的,或者至少可能构成更强大的基础。
答案 1 :(得分:1)
您可以为此编写扩展方法。 此方法具有返回值,因此它支持链接,但也更改原始的转换,因此可以在不分配的情况下使用它。
public static XElement EnsureNamespaceExists(this XElement xElement, XNamespace xNamespace)
{
string nodeName = xElement.Name.LocalName;
if (!xElement.HasAttribute("xmlns"))
{
foreach (XElement tmpElement in xElement.DescendantsAndSelf())
{
tmpElement.Name = xNamespace + tmpElement.Name.LocalName;
}
xElement = new XElement(xNamespace + nodeName, xElement.FirstNode);
}
return xElement;
}