xslt - 在规范化文本上使用深度等于

xslt - Using deep-equal on normalized text

我正在尝试 运行 deep-equal function 来比较 2 个节点序列。 对于我希望匹配的序列,唯一的区别是这里和那里有一些回车 return 和其中一个序列的附加 ID 元素。

例如:

<body>
 <section>
   <p>that's a paragraph</p>
   <p @class="p1">that's another paragraph</p>
 </section>
</body>

和:

<body>
 <section id="1">
   <p id="2">that's a 
 paragraph</p>
   <p @class="p1"  id="3">that's another paragraph</p>
 </section>
</body>

对我来说,这是一场比赛。

现在,deep-equal不喜欢回车return和id。所以我一直在尝试修改它以确保它仍然是匹配的。

使用 remove-attributes-deep,我包装了深度相等:

 <xsl:function name="functx:deep-similar" as="xs:boolean">
   <xsl:param name="seq1" as="item()*"/>
   <xsl:param name="seq2" as="item()*"/>

   <xsl:variable name="seq1-noId" select="functx:remove-attributes-deep($seq1,'id')"/>
   <xsl:variable name="seq2-noId" select="functx:remove-attributes-deep($seq2,'id')"/>

   <xsl:sequence select="every $i in 1 to max((count($seq1-noId), count($seq2-noId)))
     satisfies deep-equal($seq1-noId[$i], $seq2-noId[$i])"/>    
 </xsl:function>

这段代码基本上是来自 sequence-deep-equal 的代码,上面有 remove-attributes-deep

现在我想调整它以标准化空格。

如何规范化序列中每个节点的单个 text(),同时保留节点,以便在更新后 运行 对它们进行深度相等?我需要它在函数本身内部。

我不能删除我的文件,一些空间对我来说很重要。

我建议定义一个命名模式,在与 deep-equal:

比较之前执行您要执行的转换(即文本值规范化和 id 属性删除)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:variable name="t1">
        <body>
            <section>
                <p>that's a paragraph</p>
                <p class="p1">that's another paragraph</p>
            </section>
        </body>     
    </xsl:variable>

    <xsl:variable name="t2">
        <body>
            <section id="1">
                <p id="2">that's a 
                    paragraph</p>
                <p class="p1"  id="3">that's another paragraph</p>
            </section>
        </body>
    </xsl:variable>

    <xsl:template name="main">
        <xsl:variable name="nt1">
            <xsl:apply-templates select="$t1" mode="normalize"/>
        </xsl:variable>
        <xsl:variable name="nt2">
            <xsl:apply-templates select="$t2" mode="normalize"/>
        </xsl:variable>

        <xsl:value-of select="'deep-equal($t1, $t2): ', deep-equal($t1, $t2), '; deep-equal($nt1, $nt2): ', deep-equal($nt1, $nt2)"/>
    </xsl:template>

    <xsl:template match="@* | node()" mode="#all">
        <xsl:copy>
            <xsl:apply-templates select="@* , node()" mode="#current"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="text()" mode="normalize">
        <xsl:value-of select="normalize-space()"/>
    </xsl:template>

    <xsl:template match="@id" mode="normalize"/>

</xsl:stylesheet>

如果您不想对所有模式进行身份转换,您当然可以只为命名模式定义它,即替换

<xsl:template match="@* | node()" mode="#all">
    <xsl:copy>
        <xsl:apply-templates select="@* , node()" mode="#current"/>
    </xsl:copy>
</xsl:template>

来自

<xsl:template match="@* | node()" mode="normalize">
    <xsl:copy>
        <xsl:apply-templates select="@* , node()" mode="normalize"/>
    </xsl:copy>
</xsl:template>