XSLT 1.0:如何在变量select中选取bird前到dog的a元素(不含两者)
<a> Elements Between <dog> and <bird> in XSLT 1.0 Got it, let's work through this problem step by step. You need to pick out all <a> elements that sit after a <dog> element and before the next <bird> element (excluding both <dog> and <bird> themselves), and do this entirely within the select attribute of an XSLT variable. Even if your actual element types differ from the example, the core logic will hold. Let's walk through examples and the implementation.
Example Input XML
First, here's a sample input to demonstrate the scenario (note the random elements between <dog> and <bird>):
<root> <a id="1"/> <!-- Not selected: before <dog> --> <dog/> <a id="2"/> <!-- Selected: between <dog> and <bird> --> <b/> <a id="3"/> <!-- Selected: between <dog> and <bird> --> <c/> <bird/> <a id="4"/> <!-- Not selected: after <bird> --> </root>
Expected Output
We want to extract only the <a> elements that fall between our target <dog> and <bird>:
<a id="2"/> <a id="3"/>
XSLT 1.0 Implementation
The key is crafting an XPath expression that fits directly in the variable's select attribute. Here's the full stylesheet:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="xml" indent="yes"/> <xsl:template match="/"> <!-- Variable with the critical XPath selection logic --> <xsl:variable name="target-a-elements" select="//a[ <!-- 1. The <a> comes after at least one <dog> --> preceding-sibling::dog and <!-- 2. The <a> comes before at least one <bird> --> following-sibling::bird and <!-- 3. The closest preceding <dog> is before the closest preceding <bird> --> not(preceding-sibling::bird[1] >> preceding-sibling::dog[1]) ]"/> <!-- Output the selected elements to verify --> <selected-elements> <xsl:copy-of select="$target-a-elements"/> </selected-elements> </xsl:template> </xsl:stylesheet>
How the XPath Works
Let's break down the conditions in the select attribute to make sure it makes sense:
preceding-sibling::dog: Ensures the<a>isn't before all<dog>elements in the document.following-sibling::bird: Ensures the<a>isn't after all<bird>elements.not(preceding-sibling::bird[1] >> preceding-sibling::dog[1]): Uses XSLT 1.0's>>operator (which checks document order) to confirm that the closest preceding<bird>doesn't come after the closest preceding<dog>. This locks in that the<a>is in the interval between a<dog>and the next<bird>, not the other way around.
This logic works no matter what other element types are mixed in between (like <b> or <c> in the example) and handles cases where there are multiple <dog>/<bird> pairs in the document.
内容的提问来源于stack exchange,提问作者John Ernst

