You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XPath选择XML中两个指定CHAPTER节点间的所有节点?

解决方案:用XPath轴选择两个节点之间的所有内容

你提到的.NET里确实没有直接的SelectAllNodesBetween方法,但我们可以通过XPath的**轴(Axes)**特性来实现这个需求,不需要额外编写自定义方法。下面根据你的XML结构,分两种常见场景给出具体方案:

场景1:选择两个CHAPTER节点之间的所有节点(含自身及子节点)

如果你的目标是获取CHAPTER[@cnumber='1']到CHAPTER[@cnumber='3']之间的全部内容(包括这两个CHAPTER节点,以及中间的CHAPTER 2),可以用两种XPath写法:

简洁数字范围写法(适用于cnumber为纯数字字符串的场景)

/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[
  @cnumber='1' 
  or (@cnumber > '1' and @cnumber < '3') 
  or @cnumber='3'
]

基于兄弟节点轴的通用写法(不受数字格式限制)

/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='1'] | 
/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='1']/following-sibling::CHAPTER[preceding-sibling::CHAPTER[@cnumber='1'] and following-sibling::CHAPTER[@cnumber='3']] | 
/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='3']

场景2:选择两个VERS节点之间的所有节点(跨CHAPTER内容)

如果需要精确从CHAPTER 1下的VERS[@vnumber='1'],到CHAPTER 3下的VERS[@vnumber='1']之间的所有节点(包括这两个VERS、中间的CHAPTER 2及其子节点),可以用组合式XPath:

<!-- 起始VERS节点 -->
/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='1']/VERS[@vnumber='1'] |
<!-- 起始CHAPTER的后续兄弟节点(在结束CHAPTER之前)的所有节点(含自身和子节点) -->
/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='1']/following-sibling::CHAPTER[preceding-sibling::CHAPTER[@cnumber='1'] and following-sibling::CHAPTER[@cnumber='3']]/descendant-or-self::* |
<!-- 结束CHAPTER中,结束VERS之前的所有VERS节点 -->
/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='3']/VERS[@vnumber='1']/preceding-sibling::VERS |
<!-- 结束VERS节点 -->
/XMLBIBLE/BIBLEBOOK[@bname='1 Mose']/CHAPTER[@cnumber='3']/VERS[@vnumber='1']

整合到你的C#代码中

你可以把这个逻辑和现有代码结合,动态生成XPath:

// 提取动态参数
string targetBook = entry.NumberFrom + " " + entry.NameFrom;
string startChapter = entry.ChapterFrom;
string startVers = entry.VersFrom;
string endChapter = "3"; // 可替换为你的目标章节参数
string endVers = "1"; // 可替换为你的目标经文参数

// 构建完整XPath表达式
string xPath = $@"
/XMLBIBLE/BIBLEBOOK[@bname='{targetBook}']/CHAPTER[@cnumber='{startChapter}']/VERS[@vnumber='{startVers}'] |
/XMLBIBLE/BIBLEBOOK[@bname='{targetBook}']/CHAPTER[@cnumber='{startChapter}']/following-sibling::CHAPTER[preceding-sibling::CHAPTER[@cnumber='{startChapter}'] and following-sibling::CHAPTER[@cnumber='{endChapter}']]/descendant-or-self::* |
/XMLBIBLE/BIBLEBOOK[@bname='{targetBook}']/CHAPTER[@cnumber='{endChapter}']/VERS[@vnumber='{endVers}']/preceding-sibling::VERS |
/XMLBIBLE/BIBLEBOOK[@bname='{targetBook}']/CHAPTER[@cnumber='{endChapter}']/VERS[@vnumber='{endVers}']
";

// 执行节点选择
XmlNodeList nodeList = xmlDocument.SelectNodes(xPath);

补充提示

  • 如果XML中的cnumber和vnumber是数字类型(而非字符串),可以去掉属性值的引号,直接用@cnumber=1这类写法。
  • 如果只需要选择同级节点(不包含子节点),删除表达式中的descendant-or-self::*即可。

内容的提问来源于stack exchange,提问作者Fabian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:35:52