Using
//blockquote[* and not(*[not(self::pre)])]
This selects all blockquote elements in the XML document that have at least one child and do not have a child that is not a pre element.
Itβs just applying the double negation law :).
Note that this expression is more efficient than one that takes into account all the child elements of the element (since the selection stops right when the pre child is found).
XSLT Based Validation :
<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:template match="/"> <xsl:copy-of select="//blockquote[* and not(*[not(self::pre)])]"/> </xsl:template> </xsl:stylesheet>
When this conversion is applied to the provided XML document:
<body><div> <blockquote><pre>YES</pre></blockquote> <blockquote><p>NO</p></blockquote> <blockquote><pre>NO</pre><p>NO</p></blockquote> <blockquote><p>NO</p><pre>NO</pre></blockquote> <blockquote><pre>YES</pre> <pre>YES</pre></blockquote> <blockquote>NO</blockquote> </div></body>
an XPath expression is evaluated, and the selected nodes are copied to the output:
<blockquote> <pre>YES</pre> </blockquote> <blockquote> <pre>YES</pre> <pre>YES</pre> </blockquote>
source share