【问题标题】:XML namespace missing for parser解析器缺少 XML 命名空间
【发布时间】:2016-07-08 10:14:34
【问题描述】:

我必须解析缺少 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 命名空间的 XML,所以 xml 看起来像这样:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program>
  <scriptList>
  <script type="StartScript">
    <isUserScript>false</isUserScript>
  </script>
  </scriptList>
</program>

但应该是这样的:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<program xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <scriptList>
    <script xsi:type="StartScript">
      <isUserScript>false</isUserScript>
    </script>
  </scriptList>
</program>

type 属性确保正确的子类,例如

class StartScript : script
{...}

解析器是通过 $> xsd.exe a.xsd /classes (.Net) 从手写 xsd 自动生成的。 这是xsd:

<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
elementFormDefault="qualified" attributeFormDefault="qualified">

  <!-- Main element -->
  <xs:element name="program">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="scriptList">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="script" type="script" maxOccurs="unbounded"/>
            </xs:sequence>
          </xs:complexType>
        </xs:element>
      </xs:sequence>
    </xs:complexType>
  </xs:element>

  <xs:complexType name="script" />

  <xs:complexType name="StartScript">
    <xs:complexContent>
      <xs:extension base="script">
        <xs:all>
          <xs:element name="isUserScript" type="xs:boolean"></xs:element>
        </xs:all>
      </xs:extension>
    </xs:complexContent>
  </xs:complexType>

一个简单的解决方案是在输入 XML 上运行字符串替换(" type=\"" 到 " xsi:type=\""),但这非常难看。 有没有更好的解决方案?

【问题讨论】:

  • 你是怎么解析的?您使用的是XmlSerializer,还是其他?还有其他类型的script 还是只有StartScript
  • 在 C# 中解析很简单: _program = (new XmlSerializer(typeof(program))).Deserialize(f) as program;脚本很多,StartScript只是一个例子

标签: c# xml xsd namespaces


【解决方案1】:

您可以将您的 XML 加载到中间 LINQ to XMLXDocument,修复 &lt;script&gt; 元素上的属性命名空间,然后直接反序列化到您的最终类:

// Load to intermediate XDocument
XDocument xDoc;
using (var reader = XmlReader.Create(f))
    xDoc = XDocument.Load(reader);

// Fix namespace of "type" attributes
XNamespace xsi = "http://www.w3.org/2001/XMLSchema-instance";
foreach (var element in xDoc.Descendants("script"))
{
    var attr = element.Attribute("type");
    if (attr == null)
        continue;
    var newAttr = new XAttribute(xsi + attr.Name.LocalName, attr.Value);
    attr.Remove();
    element.Add(newAttr);
}

// Deserialize directly to final class.
var program = xDoc.Deserialize<program>();

使用扩展方法:

public static class XObjectExtensions
{
    public static T Deserialize<T>(this XContainer element, XmlSerializer serializer = null)
    {
        if (element == null)
            throw new ArgumentNullException();
        using (var reader = element.CreateReader())
            return (T)(serializer ?? new XmlSerializer(typeof(T))).Deserialize(reader);
    }
}

【讨论】:

    猜你喜欢
    • 2010-11-08
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 2014-01-10
    • 1970-01-01
    • 2021-10-24
    相关资源
    最近更新 更多