Xml 为什么XSLT不喜欢我的XPath查询?

Xml 为什么XSLT不喜欢我的XPath查询?,xml,xslt,xpath,Xml,Xslt,Xpath,我有一个XPath查询,它试图获取特定文件节点的父节点。当我在Xselerator中使用XPath求值器时,我的查询没有问题,但当我将其放入XSLT代码时,它给了我合适的条件。以下是我的XSLT代码: <xsl:template match="//*[local-name()='Wix']/*[local-name()='Fragment'][1]/*[local-name()='DirectoryRef']/*[local-name()='Directory'][./@*[local-n

我有一个XPath查询,它试图获取特定文件节点的父节点。当我在Xselerator中使用XPath求值器时,我的查询没有问题,但当我将其放入XSLT代码时,它给了我合适的条件。以下是我的XSLT代码:

<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>
有什么想法吗

编辑:以下是从较大文件中清除的相关XML:

<?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>

我想要做的就是抓取组件节点。Visual Studio给了我以下错误:谓词之外的模式中只允许使用“子”和“属性”轴。。。在\Client.exe']]/->…中,XSLT匹配模式不允许所有类型的XPath表达式,相反,模式是XPath表达式的子集。您似乎想要访问父级。。但在XSLT模式中不允许这样做,除非它位于谓词内部。因此,您需要重写您的模式,而不是foo[predicate]/。。使用*[foo[谓词]]

[编辑] 根据你最近的评论,你在做什么

<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>

假设您想要复制除添加元素的组件之外的所有内容,这可能就足够了。

XSLT匹配模式不允许所有类型的XPath表达式,而是模式是XPath表达式的子集。您似乎想要访问父级。。但在XSLT模式中不允许这样做,除非它位于谓词内部。因此,您需要重写您的模式,而不是foo[predicate]/。。使用*[foo[谓词]]

[编辑] 根据你最近的评论,你在做什么

<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>

假设您想要复制除添加元素的组件之外的所有内容,这可能就足够了。

我认为最好在选择要处理的节点的apply templates指令中添加更多的选择逻辑,而在template规则中添加更少的选择逻辑。模板规则的匹配模式可能会匹配规则可以合理用于处理的所有元素,如果您不想处理所有这些元素,然后在apply templates调用中选择您确实要处理的节点。

我认为最好在选择要处理的节点的apply templates指令中增加选择逻辑,而在template规则中减少选择逻辑。模板规则的匹配模式可能会匹配规则可以合理用于处理的所有元素,如果您不想处理所有这些元素,然后在apply templates调用中选择您确实想要处理的内容。

没有输入XML的示例就无法分辨。没有输入XML的示例就无法分辨。我对此有点困惑。在这种情况下,我应该把括号放在哪里?你的路径足够长,足以让任何人感到困惑,但我认为match=*[local name='Wix']/*[local name='Fragment'][1]/*[local name='DirectoryRef']/*[local name='DirectoryRef']/./*[local name='Directory'][./*[local name='name='name='name']]]/.[.='bin']/*[local name='Component'][./*[local name='Source'][.='!wix.SourceDeployDir\bin\Client.exe']]可能可以。您可能想告诉我们您的输入示例需要哪种输出,以便我们可以建议使用XSLT实现所需的更简单或更可读的方法。我想获取特定文件Client.exe的组件节点,以便可以插入删除文件夹参数。我还试图找到一种使用contains的更简单方法函数,但我有另一个引用Client.exe.config的组件,因此仅请求Client.exe是不起作用的。我对此有点困惑。在这种情况下,我应该将括号放在哪里?您的路径足够长,足以让任何人困惑,但我认为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']]可能可以。您可能想告诉我们您的输入示例需要哪种输出,以便我们可以建议使用XSLT实现所需的更简单或更可读的方法。我想获取特定文件Client.exe的组件节点,以便可以插入删除文件夹参数。我还试图找到一种使用contains的更简单方法函数,但我有另一个引用Client.exe.config的组件,所以仅仅请求Client.exe是不起作用的。