Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用xslt测试是否存在具有特定内容的节点_Xslt - Fatal编程技术网

使用xslt测试是否存在具有特定内容的节点

使用xslt测试是否存在具有特定内容的节点,xslt,Xslt,我正在尝试使用XSLT合并两个单独的web.xml文件中的元素。例如,如果web-1.xml和web-2.xml正在合并,并且我正在处理web-1.xml,我希望将web-2.xml中的所有元素添加到结果中,但web-1.xml中已经存在的元素除外 在XSLT表中,我加载了一个文档,该文档的servlet将通过以下方式合并到另一个文档中: <xsl:variable name="jandy" select="document('web-2.xml')"/> 我有以下规则: &l

我正在尝试使用XSLT合并两个单独的web.xml文件中的元素。例如,如果web-1.xml和web-2.xml正在合并,并且我正在处理web-1.xml,我希望将web-2.xml中的所有元素添加到结果中,但web-1.xml中已经存在的元素除外

在XSLT表中,我加载了一个文档,该文档的servlet将通过以下方式合并到另一个文档中:

<xsl:variable name="jandy" select="document('web-2.xml')"/>

我有以下规则:

<xsl:template match="webapp:web-app">
  <xsl:copy>
    <!--  Copy all of the existing content from the document being processed  -->
    <xsl:apply-templates/>      

    <!--  Merge any <servlet> elements that don't already exist into the result  -->        
    <xsl:for-each select="$jandy/webapp:web-app/webapp:servlet">
      <xsl:variable name="servlet-name"><xsl:value-of select="webapp:servlet-name"/></xsl:variable>

      <xsl:if test="not(/webapp:web-app/webapp:servlet/webapp:servlet-name[text() = $servlet-name])">
        <xsl:copy-of select="."/>
      </xsl:if>
    </xsl:for-each>

  </xsl:copy>

</xsl:template>

我遇到的问题是,如果测试正确的话,那就让它通过测试。对于上面的代码,无论给定节点的servlet name元素是否存在,测试的结果总是为false。我尝试过各种不同的测试,但都没有成功


相关文件可在和处找到(第二个web-2.xml也在那里,但StackOverflow不允许我发布三个链接)。

您的模板匹配XPATH
webapp:webapp
from
web-1.xml
和 如果您的
xsl:if
条件:
/webapp:web-app/webapp:servlet/webapp:servlet-name[text()=$servlet-name]
,您将引用绝对XPATH。尝试使用相对XPATH执行此操作:

  <xsl:if test="not(webapp:servlet/webapp:servlet-name[text() = $servlet-name])">
    <xsl:copy-of select="."/>
  </xsl:if>

我还没有检查过,所以你得试一试

此外,如果您可以提供web-1.xml和web-2.xml文件,则会更容易

编辑

下面的XSLT合并了两个文件—当输入XML的两个位置有相同类型的节(如listener)时,唯一的问题就会出现

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:webapp="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns="http://java.sun.com/xml/ns/javaee"
    xpath-default-namespace="http://java.sun.com/xml/ns/javaee">

    <xsl:output indent="yes"/>
    <xsl:variable name="jandy" select="document('web-2.xml')"/>
    <xsl:template match="/">
        <xsl:element name="web-app">
            <xsl:for-each select="webapp:web-app/*[(name() != preceding-sibling::node()[1]/name()) or (position() = 1)]">
                <xsl:variable name="nodeName" select="./name()"/>
                <xsl:variable name="web1" as="node()*">
                    <xsl:sequence select="/webapp:web-app/*[name()=$nodeName]"/>
                </xsl:variable>
                <xsl:variable name="web2" as="node()*">
                    <xsl:sequence select="$jandy/webapp:web-app/*[name() = $nodeName]"/>
                </xsl:variable>
                <xsl:copy-of select="$web1" copy-namespaces="no"/>
                <xsl:for-each select="$web2">
                    <xsl:variable name="text" select="./*[1]/text()"/>
                    <xsl:if test="count($web1[*[1]/text() = $text]) = 0">
                        <xsl:copy-of select="." copy-namespaces="no"/>
                    </xsl:if>
                </xsl:for-each>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

在for each循环之前,为第一个文档提供一个锚点:

<xsl:variable name="var" select="."/>

然后,在下列情况下使用它:

<xsl:if test="not($var/webapp:servlet/webapp:servlet-name[text() = $servlet-name])">


相对路径可能是错误的;它将使用当前上下文节点,即来自foreach的节点,并且将在错误的文档中查找。如果您想下载,我已经发布了指向这些文件的链接。我检查了您发布的*.xml文件-没有仅存在于web-2.xml文件中的servlet。哦,保存为web-2.xml的错误文档。现在已经正确上传了。这几乎可以正常工作;由于上下文节点是一个webapp:web应用,因此从$var之后的路径中删除该部分就可以了。我会给出答案,但我真的很想知道为什么会有不同,因为使用以/开始的路径似乎应该做同样的事情。@ryanmcfall,你说得对,我修复了路径。至于为什么会这样;这都是关于上下文,或者说,实际上是范围。就我所见,我发布的原始版本中没有依赖于范围的内容,因为它从文档的根节点开始。我认为这是一个问题的唯一方法是,如果因为foreach正在迭代来自不同文档的节点集,那么/引用的是该文档而不是所需的文档。是吗?@ryanmcfall,是的,就是这样。在for each循环中,
/
引用迭代元素的根。如果是变量或外部文档(通过变量访问),则
/
分别引用该变量的根或文档的根。