提问人:Michael Chen 提问时间:8/2/2023 最后编辑:Michael Chen 更新时间:8/3/2023 访问量:54
如何获取字符串中特定XML节点的范围?
How do I get the range of a specific XML node in a string?
问:
假设我有一个 XML 文档,我想从中提取标题内容的位置。
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>
鉴于文档的结构,我想找到标题的字符串范围,以便:
Range range = GetHeadingRange(xmlString);
string heading = xmlString[range]; // heading should now be "Reminder"
// How do I aquire a range like this (or an (offset, length))
我已经尝试过 XmlSerializer,但我无法从序列化程序获取任何令牌位置信息。是否有任何较低的 XmlClass 允许访问更接近输入字符串?
编辑:我需要弄清楚匹配序列的偏移量和长度。我不需要实际的标题值,因为我希望能够在原始文本中突出显示这个位置,我实际上并不关心该值。
答:
0赞
DavidG
8/2/2023
#1
最简单的方法是将 XML 解析为 XML 并遍历该树。例如:XDocument
var doc = XDocument.Parse(xmlString);
var heading = doc.Element("note") // Get note element
.Element("heading") // Now get heading element
.Value; // Finally extract the content of the heading element
// heading will contain "Reminder"
评论
1赞
Rand Random
8/2/2023
但是,这有什么关系呢?(并不是说我不知道OP在字面上是什么意思)Range
1赞
DavidG
8/2/2023
我假设 OP 认为他们需要通过字符串操作来做到这一点,并且是一个实际的 C# 范围,要传入以查找子字符串。显然,这不是必需的,所以我将其作为替代(和更好)的答案。range
0赞
Rand Random
8/2/2023
是的,Guru 也有同样的想法,没有想到 OP 想在 xml 中对 to/from 做一些事情 - 但是谁调用了注释范围的发送者和接收者?!?所以,是的,我很困惑
1赞
DavidG
8/2/2023
是的,虽然不确定我是否会给出正则表达式作为答案,但几乎可以肯定这是一种糟糕的方法。
0赞
Michael Chen
8/3/2023
是的,我知道我可以得到这样的值,但我真的需要能够弄清楚这个确切元素在原始字符串中的位置。
1赞
Guru Stron
8/2/2023
#2
一般来说,你永远不应该用正则表达式来解析XML,但对于这个特定的选择,最简单的选择是:
var s = """
<note>
<to>Tove</to>
<from>Jani</from><heading>Reminder</heading><body>Don't forget me this weekend!</body>
</note>
""";
var match = Regex.Match(s, @"<heading>(?<val>.+?)<\/heading>");
if (match.Success)
{
var matchGroup = match.Groups["val"];
Range range = matchGroup.Index..(matchGroup.Index + matchGroup.Length);
Console.WriteLine(s[range]);
}
但这是一种相当脆弱的方法,一般来说,你应该只解析 XML(参见另一个答案)
评论
0赞
Michael Chen
8/3/2023
虽然这真的不是我想在我的项目中做的事情,但似乎我目前被这样不稳定的东西困住了。我认为,像许多解析器一样,.NET 中的 Xml 解析器可能在词法分析后存储了令牌信息。
0赞
Guru Stron
8/3/2023
@MichaelChen它实际上可以存储一些 - 但它希望有用,它存储 1) 行号 + 行中的位置,而不是索引 2) 它存储节点的开始(即从 ) 3) 它存储“结束”信息但不公开它。XDocument.Parse(s, LoadOptions.PreserveWhitespace | LoadOptions.SetLineInfo)
<heading>
评论
range
GetHeadingRange
Range
"asdsad"[1..3]