0

我正在尝试使用 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。我尝试了各种不同的测试,但没有运气。

相关文件位于http://www.cs.hope.edu/~mcfall/stackoverflow/web-1.xmlhttp://www.cs.hope.edu/~mcfall/stackoverflow/transform.xslt(第二个 web-2.xml 也在那里,但 StackOverflow 不允许我发布三个链接)。

4

2 回答 2

0

您的模板与 XPATH 相匹配webapp:webappweb-1.xml如果您的xsl:if条件是:/webapp:web-app/webapp:servlet/webapp:servlet-name[text() = $servlet-name]. 尝试使用相对 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>
于 2012-05-31T20:16:53.090 回答
0

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

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

然后,在你的 if 中使用它:

<xsl:if test="not($var/webapp:servlet/webapp:servlet-name[text() = $servlet-name])">
于 2012-05-31T22:03:23.693 回答