使用xslt测试是否存在具有特定内容的节点
我正在尝试使用XSLT合并两个单独的web.xml文件中的元素。例如,如果web-1.xml和web-2.xml正在合并,并且我正在处理web-1.xml,我希望将web-2.xml中的所有元素添加到结果中,但web-1.xml中已经存在的元素除外 在XSLT表中,我加载了一个文档,该文档的servlet将通过以下方式合并到另一个文档中:使用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
<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
fromweb-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循环中,/
引用迭代元素的根。如果是变量或外部文档(通过变量访问),则/
分别引用该变量的根或文档的根。