Прежде всего, обратите внимание, что XPath основан на XML Infopath - модели XML, в которой нет «начального тега» и «конечного тега», а есть только узлы
Поэтому не следует ожидать, что выражение XPath выберет «теги» - оно выбирает узлов .
Учитывая этот факт, я интерпретируювопрос как:
Я хочу получить набор всех элементов, которые находятся между данным «начальным» элементом и заданным «конечным элементом», включая начальный и конечный элементы.
В XPath 2.0 это удобно сделать с помощью стандартного оператора пересечь .
В XPath 1.0 (который я предполагаю, что вы используете) это не так просто.Решение состоит в том, чтобы использовать формулу Кейса (по @Michael Kay) для пересечения наборов узлов :
Пересечение двух наборов узлов: $ns1
и $ns2
выбирается путем оценки следующегоВыражение XPath:
$ns1[count(.|$ns2) = count($ns2)]
Предположим, что у нас есть следующий XML-документ (как вы никогда его не предоставили):
<html>
<body>
<table>
<tr valign="top">
<td>
<table class="target">
<tr>
<td>Other Node</td>
<td>Other Node</td>
<td>Starting Node</td>
<td>Inner Node</td>
<td>Inner Node</td>
<td>Inner Node</td>
<td>Ending Node</td>
<td>Other Node</td>
<td>Other Node</td>
<td>Other Node</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
Start-элемент выбирается с помощью :
//table[@class = 'target']
//td[. = 'Starting Node']
Конечный элемент выбирается с помощью :
//table[@class = 'target']
//td[. = Ending Node']
Чтобы получить все нужные узлы, мы пересекаемследующие два набора :
Набор, состоящий из начального элемента и всех следующих элементов (назовем это $vFollowing
).
Набор, состоящий из конечного элемента и всех предыдущих элементов (мы называем это $vPreceding
).
Они выбираются, соответственно, следующими выражениями XPath :
$ vFollowing:
$vStartNode | $vStartNode/following::*
$ vPreceding:
$vEndNode | $vEndNode/preceding::*
Теперь мы можем просто применить Кейсианформула для наборов узлов $vFollowing
и $vPreceding
:
$vFollowing
[count(.|$vPreceding)
=
count($vPreceding)
]
Остается только заменить все переменные соответствующими выражениями.
Проверка на основе XSLT :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="vStartNode" select=
"//table[@class = 'target']//td[. = 'Starting Node']"/>
<xsl:variable name="vEndNode" select=
"//table[@class = 'target']//td[. = 'Ending Node']"/>
<xsl:variable name="vFollowing" select=
"$vStartNode | $vStartNode/following::*"/>
<xsl:variable name="vPreceding" select=
"$vEndNode | $vEndNode/preceding::*"/>
<xsl:template match="/">
<xsl:copy-of select=
"$vFollowing
[count(.|$vPreceding)
=
count($vPreceding)
]"/>
</xsl:template>
</xsl:stylesheet>
при применении к XML-документу выше, выражения XPath оцениваются и выводится требуемый, правильный, выбранный в результате набор узлов :
<td>Starting Node</td>
<td>Inner Node</td>
<td>Inner Node</td>
<td>Inner Node</td>
<td>Ending Node</td>