如果我有一个带有命名空间的XML文件,例如:
<root>
<h:table xmlns:h="http://www.namespaces.com/namespaceOne">
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<h:table xmlns:h="https://www.namespaces.com/namespaceTwo">
<h:name>African Coffee Table</h:name>
<h:width>80</h:width>
<h:length>120</h:length>
</h:table>
</root>
我想将所有命名空间提升到根元素,如下所示:
<root xmlns:h="http://www.namespaces.com/namespaceOne" xmlns:h1="https://www.namespaces.com/namespaceTwo">
<h:table>
<h:tr>
<h:td>Apples</h:td>
<h:td>Bananas</h:td>
</h:tr>
</h:table>
<h1:table>
<h1:name>African Coffee Table</h1:name>
<h1:width>80</h1:width>
<h1:length>120</h1:length>
</h1:table>
</root>
有没有办法做到这一点?理想情况下,自动解析冲突的命名空间前缀,如上例所示。我还没有承诺使用Linq to XML或System.Xml,所以两者都有可能。
有一个主要的制约因素:由于我所处的环境,我不能写课。我可以编写函数,但没有新的类定义。
事实证明这很简单:
var doc = XDocument.Parse(xml);
var namespaceAttributes = doc.Descendants()
.SelectMany(x => x.Attributes())
.Where(x => x.IsNamespaceDeclaration);
int count = 1;
foreach (var namespaceAttribute in namespaceAttributes)
{
doc.Root.Add(new XAttribute(XNamespace.Xmlns + $"h{count}", namespaceAttribute.Value));
namespaceAttribute.Remove();
count++;
}
我们遍历所有命名空间声明(xmlns:foo="foo"
(。对于我们找到的每个元素,我们在根元素上放置一个具有相同 URL 的命名空间属性,然后删除该属性。
演示。
请注意,如果您有多个具有相同 URL 的命名空间(例如,如果您在不同的子级上有两个大量xmlns:h="https://www.namespaces.com/namespaceOne"
(,这会做一些奇怪的事情:它会在具有相同 URL 的根元素上放置多个xmlns
声明,但所有元素都使用最后一个这样的命名空间。如果要避免这种情况,只需保留已添加到根元素的命名空间列表即可。