【问题标题】:xslt - Using deep-equal on normalized textxslt - 在规范化文本上使用 deep-equal
【发布时间】:2016-07-05 19:44:44
【问题描述】:

我正在尝试运行 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(),同时保留节点,以便在更新后可以在它们上运行 deep-equal?我需要它在函数内部。

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

【问题讨论】:

  • 你应该看看normalize-space函数
  • 是的,但它只返回一个字符串。如何使用规范化文本重建节点?
  • 为什么会有“我需要它在函数内部”的要求?我建议编写一些具有特定模式的模板,这些模板可以去除您想要去除的属性并根据需要规范化文本节点(或者也可以是属性值),然后您可以在该模式下对您的输入序列使用 apply-templates 和比较结果。

标签: xml xslt-2.0


【解决方案1】:

我建议在与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>

【讨论】:

  • 我在 XSLT 中的想法仍然不正确...非常感谢(一次又一次)没有你我该怎么办:D?学到很多!
猜你喜欢
  • 2020-02-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多