如何修复XML中缺少的名称空间前缀

时间:2017-03-27 09:03:15

标签: c# .net xml namespaces schema

我有一个XML文件,我无法自行修改。它包含以下根元素:

<foo xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" noNamespaceSchemaLocation="some.xsd">

正如您所见,xsi:缺少前缀noNamespaceSchemaLocation。这会导致XmlReader在验证时找不到架构信息。如果我添加前缀一切都很好。但正如我所说,我无法修改XML文件(除了测试)。我从外部源获取它们,我的工具应该自动验证它们。

是否有可能在没有XmlReader前缀的情况下noNamespaceSchemaLocation解释xsi:?我不想在预处理步骤或类似的东西中在XML中添加前缀,因为源应该保持原样。

2 个答案:

答案 0 :(得分:2)

XML是错误的,您需要修复它。要么让供应商提高他们发送的产品的质量,要么在抵达时进行修理。

我不知道你为什么要保留破碎的来源(所有的质量标准都说这是不好的做法),但它确实可以保留破碎的原件和修复过的原件。版本

答案 1 :(得分:1)

XmlReader的内部是丑陋 无证件。所以这个解决方案就像玩火。

我的建议是:XmlTextReader“添加”缺少的命名空间。您可以将此FixingXmlTextReader直接提供给XDocument.Load()或者您可以将其提供给XmlTextReader / XmlValidatingReader(他们都有一个接受一个的构造函数/ Create XmlReader作为参数)

public class FixingXmlTextReader : XmlTextReader
{
    public override string NamespaceURI
    {
        get
        {
            if (NodeType == XmlNodeType.Attribute && base.LocalName == "noNamespaceSchemaLocation")
            {
                return NameTable.Add("http://www.w3.org/2001/XMLSchema-instance");
            }

            return base.NamespaceURI;
        }
    }

    public override string Prefix
    {
        get
        {
            if (NodeType == XmlNodeType.Attribute && base.NamespaceURI == string.Empty && base.LocalName == "noNamespaceSchemaLocation")
            {
                return NameTable.Add("xsi");
            }

            return base.Prefix;
        }
    }

    public override string Name
    {
        get
        {
            if (NodeType == XmlNodeType.Attribute && base.NamespaceURI == string.Empty && base.LocalName == "noNamespaceSchemaLocation")
            {
                return NameTable.Add(Prefix + ":" + LocalName);
            }

            return base.Name;
        }
    }

    public override string GetAttribute(string localName, string namespaceURI)
    {
        if (localName == "noNamespaceSchemaLocation" && namespaceURI == "http://www.w3.org/2001/XMLSchema-instance")
        {
            namespaceURI = string.Empty;
        }

        return base.GetAttribute(localName, namespaceURI);
    }

    public override string GetAttribute(string name)
    {
        if (name == "xsi:noNamespaceSchemaLocation")
        {
            name = "noNamespaceSchemaLocation";
        }

        return base.GetAttribute(name);
    }

    // There are tons of constructors, take the ones you need
    public FixingXmlTextReader(Stream stream) : base(stream)
    {
    }

    public FixingXmlTextReader(TextReader input) : base(input)
    {
    }

    public FixingXmlTextReader(string url) : base(url)
    {
    }
}

像:

using (var reader = new FixingXmlTextReader("XMLFile1.xml"))
using (var reader2 = XmlReader.Create(reader, new XmlReaderSettings
{
}))
{
    // Use the reader2!
}

using (var reader = new FixingXmlTextReader("XMLFile1.xml"))
{
    var xdoc = new XmlDocument();
    xdoc.Load(reader);
}