如何在XSLT中使用preceding-sibling限制for-each,仅读取x=0元素前的内容?
Solution to Select Elements Before
<line x="0.0"/> Your current XSLT code has a couple of issues with the XPath logic that's preventing it from working correctly. Let's fix that and break down what's going on.
Correct XSLT Code (XSLT 1.0 Compatible)
Here's a working snippet that selects all elements inside <g id='NOCUT'> that appear before the first <line x="0.0"/>:
<xsl:template match="/"> <!-- Target the specific g element first --> <xsl:for-each select="svg/g[@id='NOCUT']/*[not(preceding-sibling::line[@x='0.0'])]"> <!-- Replace this with your processing logic --> <xsl:copy-of select="."/> </xsl:for-each> </xsl:template>
Why Your Original Code Failed
Let's look at the key problems in your approach:
- Incorrect Context in the Second
for-each: When you use<xsl:for-each select="svg[g/@id='NOCUT']">, the context becomes the<svg>element. Your secondfor-eachusesg/*, which would select all children of all<g>elements in the<svg>—but you should be targeting only the<g>withid='NOCUT'using*g[@id='NOCUT']/**. - Wrong Predicate Logic: The predicate
*preceding-sibling::node[line/@x = '0.0']*is looking for a preceding sibling node that has a<line>child withx='0.0'. But the<line x="0.0"/>is a direct sibling element, not a child of another sibling node. Instead, you need to check if the current element does not have any preceding sibling<line>withx='0.0'(which is what*not(preceding-sibling::line[@x='0.0'])*does).
For XSLT 2.0+ Users (More Readable)
If you're using a processor that supports XSLT 2.0 or higher, you can use the *<<* operator (document order comparison) for a more intuitive query:
<xsl:template match="/"> <xsl:variable name="target-line" select="svg/g[@id='NOCUT']/line[@x='0.0'][1]"/> <xsl:for-each select="svg/g[@id='NOCUT']/*[. << $target-line]"> <!-- Your processing here --> <xsl:copy-of select="."/> </xsl:for-each> </xsl:template>
This first stores the first occurrence of <line x="0.0"/> in a variable, then selects all elements that come before it in document order.
Edge Cases to Consider
- If there's no
<line x="0.0"/>in the<g id='NOCUT'>, both approaches will select all child elements of the<g>. - If there are multiple
<line x="0.0"/>elements, both approaches will only select elements before the first occurrence (which is likely what you want).
内容的提问来源于stack exchange,提问作者HarsH
相关产品推荐
相关产品推荐

