0
votes

Is it possible to write a template rule, where the match attribute use preceding-sibling operator excluding certain types of nodes? I try to explain my self. I have this xml input document:

<?xml version="1.0"?>
  <graph>
   <vertex name="A"/>
   <edge name="AB" />
   <tag name="tagA"/>
   <vertex name="C"/>
   <edge name="AB"/>
   <vertex name="AA"/>
   <edge name="AAD"/>
   <vertex name="D"/>
   <vertex name="AAA"/>
   <tag name="tagE"/>
   <vertex name="E"/>
  </graph>

What I want to extract is a vertex whose preceding-sibling excluding all the nodes of type tag, is a vertex with name containing A char. In this case, the output I desire is: <vertex name="E"/>

I don't know which template rule I should write, because I know how to set a constraint for the first preceding sibling of a given type:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:exsl="http://exslt.org/common"
  exclude-result-prefixes="exsl">
  <xsl:template match="vertex[preceding-sibling::vertex[1]
    [self::vertex[contains(@name, 'A')]]]">
  <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>


I am able to write a match for the first preceding-sibling of a node, without specifying any type, but it does not help me in this situation. The problem here is I would like to tell to XSLT to consider all preceding sibling, but not the one of type tag.

1

1 Answers

1
votes

I think the match expression you want is this...

 <xsl:template match="vertex[preceding-sibling::*[not(self::tag)][1][self::vertex[contains(@name, 'A')]]]">

Doing preceding-sibling::vertex[1] will find the first vertex that precedes the current node, which might not be the most immediately preceding sibling. Doing preceding-sibling::*[not(self::tag)][1] will get the most preceding sibling that is not a tag, which you can then check to be a vertex.