使用未定义的名称空间前缀解析(伪 - )XML

时间:2013-08-19 05:43:55

标签: linq-to-xml

我有许多具有类似XML结构的文件,但具有未定义的名称空间前缀。我只需要从这些文件中提取数据,而不是验证它们。在尝试使用XElement.LoadXDocument.Load进行解析时,我会收到undefined prefix个异常。我该怎么做(优选使用LINQ to XML)?

1 个答案:

答案 0 :(得分:1)

如果您提前知道前缀,请将它们自己添加到虚拟根节点,然后将文档添加到该虚拟节点。然后,您可以解析和查询您的实际文档。但是,您必须在加载/解析之前将其添加到未解析的XML内容中。幸运的是,完成起来可能相对简单。

如,

XElement ParseFragment(string fragment, IDictionary<string, XNamespace> namespaces)
{
    var namespaceDefs = namespaces
        .Select(kvp => String.Format("xmlns:{0}=\"{1}\"", kvp.Key, kvp.Value.NamespaceName));
    var xml = String.Format(
        "<root {0}>{1}</root>",
        String.Join(" ", namespaceDefs),
        fragment);
    var root = XElement.Parse(xml);
    return root.Elements().Single();
}
XElement LoadFragment(TextReader fragmentReader, IDictionary<string, XNamespace> namespaces)
{
    var namespaceDefs = namespaces
        .Select(kvp => String.Format("xmlns:{0}=\"{1}\"", kvp.Key, kvp.Value.NamespaceName));
    var sb = new StringBuilder();
    sb.AppendLine(String.Format("<root {0}>", String.Join(" ", namespaceDefs)));
    sb.AppendLine(fragmentReader.ReadToEnd());
    sb.AppendLine("</root>");
    var root = XElement.Load(new StringReader(sb.ToString()));
    return root.Elements().Single();
}

然后你可以解析/加载和查询元素:

var fragment = @"<a:root><b:child>foo</b:child><b:child>bar</b:child></a:root>";
var namespaces = new Dictionary<string, XNamespace>
{
    { "a", "http://a.com" },
    { "b", "http://b.com" },
};
var element = ParseFragment(fragment, namespaces);
var b = namespaces["b"];
var childValues = element
    .Descendants(b + "child")
    .Select(child => (string)child);