【问题标题】:How to fix missing namespace prefix in XML如何修复 XML 中缺少的命名空间前缀
【发布时间】:2017-08-19 21:45:13
【问题描述】:

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

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

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

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

【问题讨论】:

  • 根据您的外部来源,您为什么不为他们提交错误报告?
  • 如何验证您的 Xml? XmlValidatingReader?
  • @Staeff 不幸的是,这没用。他们不会修复它,因为他们不会验证自己的来源。这只是冰山一角。你不会相信他们称之为 XML 的东西。当我们需要数据时,我们必须处理它。我们取得了一些小胜利,但如果他们改变某些东西,则需要几个月的时间。
  • @xanatos XmlReaderXmlReaderSettings
  • @xanatos 如何使用 XmlReader 和 XmlReadersettings 如果我的包含 XSD 的 Uri 具有前缀,例如 foo://path/name.xsd

标签: c# .net xml namespaces schema


【解决方案1】:

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

我不知道您为什么要保留损坏的源代码(所有质量标准都认为这是不好的做法),但当然可以保留损坏的原始版本和修复后的版本。

【讨论】:

  • 可悲的是,这是我工作生活的故事。我得到废话,必须从中获得黄金。这些来源是旧的,没有人觉得有责任。由于访问限制,我无法自己修复它们。不过谢谢你的回复。我会尝试说服某人解决这个问题。
  • 从 SO 看来,这似乎是一个常见问题,即组织抱怨错误数据的次数几乎没有他们抱怨的次数多,例如,如果他们收到了错误的微芯片。他们应该。
【解决方案2】:

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);
}

【讨论】:

  • 不幸的是,这不起作用。但也许我用错了。我尝试了以下代码:using (FixingXmlTextReader fixingReader = new FixingXmlTextReader(file)) using (XmlReader reader = XmlReader.Create(fixingReader, settings)) { while (reader.Read()) ; } 调试器只进入NamespaceURI getter,但没有进入FixingXmlTextReader 的其他属性/方法。
  • @RobertS。它不会进入任何地方......我添加了不必要的重载。但遗憾的是,正如我所写的,XmlReader 的工作并不是一门精确的科学:-(
  • @RobertS。在设置中添加:ValidationType = ValidationType.Schema, ValidationFlags = System.Xml.Schema.XmlSchemaValidationFlags.ProcessSchemaLocation, XmlResolver = new XmlUrlResolver()
  • @RobertS。找到问题了……重试……XmlReader里面有一个“有趣”的字符串缓存……我不知道。
  • 非常感谢您的努力。现在可以了。 ;) 但我必须接受迈克尔斯的回答,因为他是对的:修复错误的来源比创建解决方法来处理它们要好。但我对你的回答竖起了大拇指。 :) 再次感谢。
猜你喜欢
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
  • 2019-06-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多