使用C#删除XML中的默认命名空间属性 - 不能通过ref传递对象然后迭代

时间:2012-04-17 09:55:07

标签: c# xml namespaces xml-namespaces

我目前正在处理一些有问题的代码,这些代码旨在从XML文档中删除所有命名空间并将其重新添加到标头中。我们使用它是因为我们摄取非常大的xml文档,然后以小片段重新提供它们,因此每个项目都需要复制父文档中的命名空间。

XML首先作为XmlDocument加载,然后传递给删除名称空间的函数:

        _fullXml = new XmlDocument();
        _fullXml.LoadXml(itemXml);
        RemoveNamespaceAttributes(_fullXml.DocumentElement);

remove函数遍历整个文档,查找命名空间并删除它们。它看起来像这样:

    private void RemoveNamespaceAttributes(XmlNode node){

        if (node.Attributes != null)
        {
            for (int i = node.Attributes.Count - 1; i >= 0; i--)
            {
                if (node.Attributes[i].Name.Contains(':') || node.Attributes[i].Name == "xmlns")
                    node.Attributes.Remove(node.Attributes[i]);
            }
        }

        foreach (XmlNode n in node.ChildNodes)
        {
            RemoveNamespaceAttributes(n);
        }
    }

但是,我发现它不起作用 - 它保留了所有命名空间。

如果使用调试器迭代代码,那么它看起来正在做它应该做的事情 - 节点对象的名称空间属性被删除了。但原始的_fullXml文档保持不变。我认为这是因为该函数正在查看传递给它的数据的克隆,而不是原始数据。

所以我的第一个想法是通过ref传递它。但我不能这样做,因为foreach循环中函数的迭代部分有编译错误 - 你不能通过引用传递对象n。

第二个想法是传递整个_fullXml文档,但这也不起作用,猜测因为它仍然是克隆。

所以看起来我需要解决通过ref传递文档然后遍历节点以删除所有命名空间的问题。这显然需要重新设计这个代码片段,但我看不到一个好方法。有人可以帮忙吗?

干杯, 马特

2 个答案:

答案 0 :(得分:0)

要删除名称空间,可以这样做:

void StripNamespaces(XElement input, XElement output)
{
    foreach (XElement child in input.Elements())
    {
        XElement clone = new XElement(child.Name.LocalName);
        output.Add(clone);
        StripNamespaces(child, clone);
    }
    foreach (XAttribute attr in input.Attributes())
    {
        try
        {
            output.Add(new XAttribute(attr.Name.LocalName, attr.Value));
        }
        catch (Exception e)
        {
            // Decide how to handle duplicate attributes
            //if(e.Message.StartsWith("Duplicate attribute"))
            //output.Add(new XAttribute(attr.Name.LocalName, attr.Value));
        }
    }
}

您可以这样称呼它:

XElement result = new XElement("root");
StripNamespaces(NamespaceXml, result);

答案 1 :(得分:0)

我不是100%确定没有这种情况的失败案例,但我发现你可以做到

string x = Regex.Replace(xml, @"(xmlns:?|xsi:?)(.*?)=""(.*?)""", "");

在原始xml上删除命名空间。

这可能不是解决这个问题的最好方法,但我想我会把它放在那里。