.NET XML反序列化忽略名称空间

use*_*428 9 xml vb.net xml-serialization xml-namespaces

我在所有相同的模式/结构之后获得了数千个XML文件.我实现了IXmlSerializable,因此我自己阅读元素和属性.

我的问题是这些文件都使用不同的虚假命名空间.这些文件来自另一个来源,所以我无法改变它:D另外,对于我来说,有太多这些命名空间只是构建一个可能的命名空间数组并将其传递给xmlserializer.

现在,如果我没有指定命名空间,它会抛出[xmlns:ns0 ="http://tempuri.org/abcd.xsd"不是预期的]错误.

我希望能够告诉序列化程序在反序列化我的对象时只是忽略命名空间并且只需触发ReadXML.或者只是能够告诉它接受任何"http://tempuri.org/"命名空间.

那可能吗?

我想尽量避免修改文件.

谢谢!

Joh*_*son 0

它不是关于如何告诉 XmlSerialiser 忽略命名空间的问题的答案,而是一种解决方法。您可以在序列化 xml 之前使用 xslt 转换从 xml 中去除命名空间。

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

  <xsl:template match="/|comment()|processing-instruction()">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="@*|node()"/>
    </xsl:element>
  </xsl:template>

  <xsl:template match="@*">
    <xsl:attribute name="{local-name()}">
      <xsl:value-of select="."/>
    </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

有几个扩展方法作为辅助方法,可能会有点棘手,但我会尝试:

/// <summary>
/// Transforms the xmldocument to remove all namespaces using xslt
/// http://stackoverflow.com/questions/987135/how-to-remove-all-namespaces-from-xml-with-c
/// http://msdn.microsoft.com/en-us/library/42d26t30.aspx
/// </summary>
/// <param name="xmlDocument"></param>
/// <param name="indent"></param>
public static XmlDocument RemoveXmlNameSpaces(this XmlDocument xmlDocument, bool indent = true)
{
    return xmlDocument.ApplyXsltTransform(Properties.Resources.RemoveNamespaces, indent);
}

public static XmlDocument ApplyXsltTransform(this XmlDocument xmlDocument, string xsltString,bool indent= true)
{
    var xslCompiledTransform = new XslCompiledTransform();
    Encoding encoding;
    if (xmlDocument.GetEncoding() == null)
    {
        encoding = DefaultEncoding;
    }
    else
    {
        encoding = Encoding.GetEncoding(xmlDocument.GetXmlDeclaration().Encoding);
    }
    using (var xmlTextReader = xsltString.GetXmlTextReader())
    {
        xslCompiledTransform.Load(xmlTextReader);
    }
    XPathDocument xPathDocument = null;
    using (XmlTextReader xmlTextReader = xmlDocument.OuterXml.GetXmlTextReader())
    {
        xPathDocument = new XPathDocument(xmlTextReader);
    }
    using (var memoryStream = new MemoryStream())
    {
        using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream, new XmlWriterSettings()
            {
                Encoding = encoding,
                Indent = indent
            }))
        {
            xslCompiledTransform.Transform(xPathDocument, xmlWriter);
        }
        memoryStream.Position = 0;
        using (var streamReader = new StreamReader(memoryStream, encoding))
        {
            string readToEnd = streamReader.ReadToEnd();
            return readToEnd.ToXmlDocument();
        }
    }
}

public static Encoding GetEncoding(this XmlDocument xmlDocument)
{
    XmlDeclaration xmlDeclaration = xmlDocument.GetXmlDeclaration();
    if (xmlDeclaration == null)
        return null;
    return Encoding.GetEncoding(xmlDeclaration.Encoding);
}

public static XmlDeclaration GetXmlDeclaration(this XmlDocument xmlDocument)
{
    XmlDeclaration xmlDeclaration = null;
    if (xmlDocument.HasChildNodes)
        xmlDeclaration = xmlDocument.FirstChild as XmlDeclaration;
    return xmlDeclaration;
}

public static XmlTextReader GetXmlTextReader(this string xml)
{
    return new XmlTextReader(new StringReader(xml));
}
Run Code Online (Sandbox Code Playgroud)