我正在尝试使用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>
我遇到的问题是如果正确的话进行测试。使用上面的代码,测试总是计算为false,是否存在具有给定节点的servlet-name元素。我尝试了各种不同的测试,但没有运气。
相关文件位于http://www.cs.hope.edu/~mcfall/stackoverflow/web-1.xml和http://www.cs.hope.edu/~mcfall/stackoverflow/transform.xslt(第二个web-2.xml也可以,但StackOverflow不允许我发布三个链接)。
答案 0 :(得分:0)
您的模板与来自webapp:webapp
的XPATH 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的两个位置存在相同类型的部分(如侦听器)时,会出现唯一的问题。
<?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>
答案 1 :(得分:0)
在for-each循环之前为第一个文档提供锚点:
<xsl:variable name="var" select="."/>
然后,在你的if:
中使用它<xsl:if test="not($var/webapp:servlet/webapp:servlet-name[text() = $servlet-name])">