Some correct XPath expressions don't work as expected

I'm doing some XML transform on a file generated by WiX after harvesting registry data. For those who are unfamiliar with WiX, just consider I'm trying to do XML transfer on a XML file, no matter where it is coming from. The issue I'm experiencing is: when I use XPath like

match="node()[name() = 'File'][not(@KeyPath)]"

then the matching works fine and it finds all those File nodes that are missing the KeyPath attribute in it, however, if I use another expression of XPath like


then it doesn't find any match.

In general I cannot use the standard XPaths with /, //, ., .., however, a piece below with an XPath example in it works well

<xsl:template match="node()[name() = 'File']
                               [contains(@Source, 'First.dll') or 
                                contains(@Source, 'Second.dll')]
            <xsl:apply-templates select="@* | node()"/>
            <xsl:attribute name="Assembly">.net</xsl:attribute>
            <xsl:attribute name="KeyPath">yes</xsl:attribute>

but something like /bookstore/book[@lang='en'] would not work. Perhaps, I'm missing some descriptions at the beginning of my XSL file to enable recognition of Xpaths like this.

1 answer

  • answered 2017-01-11 14:26 Tim C

    This is because the nodes in the XML file are almost certainly in a namespace

    <Wix xmlns="">

    Your expression //File[not(@KeyPath)] is looking for a File element that is is no namespace. You need to account for the namespace in your XSLT

    So, bind a prefix to it on the xsl:stylesheet like so...

    <xsl:stylesheet version="1.0"
                    xmlns:wix="" />

    Then your match expression becomes this..

    <xsl:template match="//wix:File[not(@KeyPath)]" />

    In fact, the // is not necessary here in a match. This will work too

    <xsl:template match="wix:File[not(@KeyPath)]" />