Reputation: 16137
I have an XPath query that's trying to grab the parent of a specific file node. When I used the XPath evaluator in Xselerator it was fine with my query, but when I put it into my XSLT code, it gives me fits. Here's my XSLT code:
<xsl:template match="//*[local-name()='Wix']/*[local-name()='Fragment'][1]/*[local-name()='DirectoryRef']/*[local-name()='Directory'][./@*[local-name()='Name'][.='bin']]/*[local-name()='Component']/*[local-name()='File'][./@*[local-name()='Source'][.='!(wix.SourceDeployDir)\bin\Client.exe']]/..">
<xsl:copy>
<xsl:apply-templates select="@* | node()" />
<xsl:element name="RemoveFolder" namespace="{namespace-uri()}">
<xsl:attribute name="Id">DeleteShortcutFolder</xsl:attribute>
<xsl:attribute name="Directory">DesktopFolder</xsl:attribute>
<xsl:attribute name="On">uninstall</xsl:attribute>
</xsl:element>
</xsl:copy>
Any ideas?
EDIT: Here's the relevant XML (cleaned up from the larger file):
<?xml version="1.0" encoding="utf-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="INSTALLLOCATION">
<Directory Id="dirBD8892FBCC64DA5924D7F747259B8B87" Name="bin">
<Component Id="cmp92DC8F5323DA73C053179076052F92FF" Guid="{533500C1-ACB2-4A8D-866C-7CDB1DE75524}">
<File Id="fil7C1FC50442FC92D227AD1EDC1E6D259F" KeyPath="yes" Source="!(wix.SourceDeployDir)\bin\Client.exe">
<Shortcut Id="startmenuAdv" Directory="DesktopFolder" Advertise="yes" Name="!(wix.ProductName)" WorkingDirectory="INSTALLDIR" Icon="Icon.exe">
<Icon Id="Icon.exe" SourceFile="!(wix.SourceDeployDir)\Safeguard.SPI2.Client.exe" />
</Shortcut>
<netfx:NativeImage Id="ClientNativeImageId" Platform="64bit" Priority="0" AppBaseDirectory="INSTALLLOCATION" xmlns:netfx="http://schemas.microsoft.com/wix/NetFxExtension" />
</File>
</Component></Directory></DirectoryRef></Fragment></Wix>
All I want to be able to do is grab the Component node. Visual Studio is giving me the following error: Only 'child' and 'attribute' axes are allowed in a pattern outside predicates. ...in\Client.exe']]/ -->..<--
Upvotes: 1
Views: 1621
Reputation: 167401
Well an XSLT match pattern does not allow all type of XPath expressions, instead patterns are a subset of XPath expressions. You seem to want to access the parent ..
but you are not allowed to do that in an XSLT pattern, unless it is inside of a predicate. So you will need to rewrite your pattern, instead of foo[predicate]/..
use *[foo[predicate]]
.
[edit] Based on your latest comment doing
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template xmlns:wi="http://schemas.microsoft.com/wix/2006/wi"
match="wi:Component[wi:File[@Source[. = '!(wix.SourceDeployDir)\bin\Client.exe']]]">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
<xsl:element name="RemoveFolder" namespace="{namespace-uri()}">
<xsl:attribute name="Id">DeleteShortcutFolder</xsl:attribute>
<xsl:attribute name="Directory">DesktopFolder</xsl:attribute>
<xsl:attribute name="On">uninstall</xsl:attribute>
</xsl:element>
</xsl:copy>
</xsl:template>
might suffice (assuming you want to copy everything but the Component where you add an element.
Upvotes: 5
Reputation: 163262
I think it would be better to put more of the selection logic in the apply-templates instruction that selects the nodes to be processed, and less in the template rule. The match pattern for the template rule should probably match all elements that the rule could reasonably be used to process, and if you don't want to process all those elements, then select the ones you do want to process in the apply-templates call.
Upvotes: 1