获取XElement在原始文档中的位置和长度

时间:2019-11-25 11:41:15

标签: c# xml position linq-to-xml

我正在解析特定节点的XML文档,并希望稍后在ui中显示xml文档,突出显示特定部分。为此,我需要知道元素在文档文本中的位置及其长度。

到目前为止,我发现,在加载XDocument时,我应该指定LoadOptions.SetLineInfo,以便至少可以在原始xml字符串中获得位置。这给了我char,元素的名称开始于char,所以我应该减去一个,以得到标签的实际开始。但是,我无法找到一种方法来获取结束元素的位置。

到目前为止,我已经尝试过(使用.Dump()的LinqPad代码,如有必要,可以用Console.WriteLine代替),这是基本测试代码:

var xml = @"<xml>
  <myElement>
    <someProperty attribu=""attrVal1"" />
    <someOtherProp />
  </myElement>
</xml>";
// xml.Length => 105 (Note, there should be a TAB instead of four spaces before `<someOtherProp />`,
//                    to demonstrate problems)

var doc = XDocument.Parse(xml, LoadOptions.SetLineInfo);

var li = (IXmlLineInfo)doc;
$"{li.LineNumber - 1}:{li.LinePosition - 1}~{GetLen(doc.Root)}".Dump();

foreach (var el in doc.XPathSelectElements("//myElement/*"))
{
    li = (IXmlLineInfo) el;
    $"{li.LineNumber - 1}:{li.LinePosition - 1}~{GetLen(el)}".Dump();
}

现在,我对GetLen的实现:

首次尝试:使用.ToString()

int GetLen(XElement el)
{
    return el.ToString().Length;
}

这将重新格式化代码,因此上面注释中提到的TAB将改为扩展为四个空格。 doc将是108个字符,而不是现在的105个字符。因此,这不是一个选择。

第二次尝试:使用XmlReader

int GetLen(XElement el)
{
    using (var r = el.CreateReader())
    {
        r.MoveToContent();
        var ox = r.ReadOuterXml();
        return ox.Length;
    }
}

这将丢弃所有不必要的空格,从而缩短长度(doc为86)。因此,这也不是一种选择。

除了我自己想避免做的XML解析之外,我没有找到其他有意义的方法来完成我需要的工作。有谁知道我还能尝试什么?

我当然可以读取xml并重新格式化,然后使用其中一个选项。但是,由于XML是由外部方提供的,并且我们想告诉他们在哪里发现错误,所以最好知道它们的索引,而不是重新格式化后的索引。

感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

似乎这是当前不可能的。相反,我们选择生成指向确切元素的XPath表达式。这样,我们可以将格式设置留给UI希望执行的任何操作,但始终具有正确的元素。