如何利用IXmlLineInfo查找XML标签闭合前末尾空格节点并获取行位置
嘿,我来帮你搞定这两个XML空格检测的问题!下面分两部分详细说明实现方案,都是基于.NET的XmlReader和IXmlLineInfo接口来做的。
一、查找XML中值末尾带空格的节点
这个需求是要找出元素文本内容末尾带有空格的节点,我们可以用XmlReader遍历所有元素,然后检查文本值的结尾是否有空格。同时借助IXmlLineInfo可以直接获取该节点的行号和位置。
实现代码(C#)
using System; using System.Xml; public class XmlTrailingSpaceChecker { public static void DetectTrailingSpaceInNodes(string xmlFilePath) { // 创建XmlReader,默认配置即可 using (XmlReader reader = XmlReader.Create(xmlFilePath)) { while (reader.Read()) { // 只处理非空元素节点 if (reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement) { string elementText = reader.ReadElementContentAsString(); // 检查文本是否以空格结尾 if (!string.IsNullOrWhiteSpace(elementText) && elementText.EndsWith(" ")) { // 利用IXmlLineInfo获取位置信息 if (reader is IXmlLineInfo lineInfo && lineInfo.HasLineInfo()) { Console.WriteLine($"Whitespace found at position {lineInfo.LineNumber},{lineInfo.LinePosition} (node <{reader.Name}> text trailing space)"); } else { Console.WriteLine($"Whitespace found in node <{reader.Name}> (position info unavailable)"); } } } } } } }
针对你提供的示例XML,运行这段代码会输出:
Whitespace found at position 3,27 (node
text trailing space)
Whitespace found at position 5,20 (nodetext trailing space)
二、使用IXmlLineInfo查找标签闭合前的空格
这个需求要定位的是元素结束标签(比如</child2>)前面的空格,这里有个关键细节:XmlReader默认会忽略空白节点,所以必须先修改配置保留空白,才能捕获到这些空格。
实现代码(C#)
using System; using System.Xml; public class XmlClosingTagWhitespaceChecker { public static void DetectWhitespaceBeforeClosingTags(string xmlFilePath) { XmlReaderSettings settings = new XmlReaderSettings { IgnoreWhitespace = false, // 必须关闭空白忽略,才能读取到闭合标签前的空格节点 ConformanceLevel = ConformanceLevel.Document }; using (XmlReader reader = XmlReader.Create(xmlFilePath, settings)) { string currentElementName = null; while (reader.Read()) { // 记录当前正在处理的元素名称 if (reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement) { currentElementName = reader.Name; } // 检测空白节点,且下一个节点是对应元素的结束标签 else if (reader.NodeType == XmlNodeType.Whitespace && !string.IsNullOrEmpty(currentElementName)) { // 先读取下一个节点,判断是否是当前元素的结束标签 if (reader.Read() && reader.NodeType == XmlNodeType.EndElement && reader.Name == currentElementName) { // 回退到空白节点,获取它的位置信息 reader.ReadToPreviousSibling(); if (reader is IXmlLineInfo whitespaceLineInfo && whitespaceLineInfo.HasLineInfo()) { Console.WriteLine($"Whitespace found at position {whitespaceLineInfo.LineNumber},{whitespaceLineInfo.LinePosition} (before closing tag </{currentElementName}>)"); } // 再读回结束标签,继续遍历 reader.Read(); } else { // 如果不是目标结束标签,回退到空白节点 reader.ReadToPreviousSibling(); } } } } } }
关键说明
- 一定要设置
IgnoreWhitespace = false,否则所有标签间的空白都会被XmlReader跳过,根本无法检测到闭合标签前的空格。 - 大部分.NET内置的XmlReader实现(比如
XmlTextReader、XmlReader.Create生成的阅读器)都支持IXmlLineInfo接口,可以直接获取行号和位置。
针对你的示例XML,运行这段代码会输出:
Whitespace found at position 3,26 (before closing tag )
Whitespace found at position 5,19 (before closing tag )
额外提示
如果是处理XML字符串而不是本地文件,只需要把XmlReader.Create(xmlFilePath)换成XmlReader.Create(new StringReader(xmlContent))即可(记得引用System.IO命名空间)。另外如果XML包含CDATA段或转义字符,需要额外处理避免误判哦。
内容的提问来源于stack exchange,提问作者Bumba

