xslt - 在规范化文本

时间:2016-07-05 08:24:57

标签: xml xslt-2.0

我正在尝试运行deep-equal function来比较2个节点序列。 对于我期望匹配的序列,唯一的区别是这里和那里的一些回车以及其中一个序列的附加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不喜欢回车和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()进行规范化,同时保留节点,以便在更新后我可以在它们上运行深度相等?我需要它在函数本身内部。

我无法删除文件,有些空格对我来说至关重要。

1 个答案:

答案 0 :(得分:1)

我建议在与id比较之前,定义一个执行转换(即文本值规范化和deep-equal属性删除)的命名模式:

<?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>