7

我正在尝试创建一个 XPath 查询,每次都会获得 549 个字符的文本。文本应该是关于相关主题的,在下面的例子中是orangesorapplespears。如果页面上不存在包含这些单词的元素,那么我希望 XPath 查询更容易在页面上找到目标/不太具体的文本。

所以为了澄清,我正在尝试创建一个 XPath 查询来查找包含特定类型文本的元素,如果使用下面的查询找到 549 个或更多字符,那么我们就完成了,如果没有找到或者返回的文本是少于 549 个字符,我希望 XPath 查询在页面上获取任何段落形式的文本(除了来自按钮、链接、菜单等的文本之外,任何文本都可以工作)并返回该文本的 549 个字符,如果结果字符串少于 549 个字符我想将这两个查询与以下内容连接起来:...在中间。

   substring(normalize-space(//*[self::p or self::div][contains(text(),'apples') or contains(text(),'oranges') or contains(text(),'pears')]), 0, 549)

我一直在努力解决这个问题,如果有任何建议,我将不胜感激!

提前谢谢了!

4

1 回答 1

10

是的。xpath 中有一个string-length()函数可以在谓词中使用:

substring(normalize-space(//*[string-length( text()) > 549 and (... other conditions ...)]),0,549)

请参阅“ XPath 中是否有“if -then - else”语句? ”了解如何执行条件语句来确定是否需要添加省略号。

从上面的 SO 问题中改编一个例子:

if (fn:string-length(normalize-space(//*[self::p or self::div][contains(text(),'apples']) > 549)
        then (concat( fn:substring(normalize-space(//*[self::p or self::div][contains(text(),'apples']), 0, 5490), "...") )
        else (normalize-space(//*[self::p or self::div][contains(text(),'apples']))

在我看来,这在 XPath 中确实很复杂。如果您可以使用 XQuery,那么您将获得一个更具可读性的转换:

for $text in normalize-space(//*[self::p or self::div])
where $text[contains(text(),'apples' or ...]
return
    if (string-length( $text) > 549) then
        concat( substring( $text, 0, 549), "...")
    else
        $text

我怀疑这实际上可以通过多个嵌套的 for 语句进一步优化(以提高可读性、维护性),以处理您需要的各种结果。

如果使用 XSL:

<xsl:template match="//*[self::p or self::div][contains(text(),'apples' or ...]">
    <xsl:variable name="text" select="normalize-space( . )" />
    <xsl:choose>
        <xsl:when test="string-length( $text)">
            <xsl:value-of select="substring( $text, 0, 549)"/>...
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

您还可以使用xpath 函数,通过构造正则表达式matches()来避免有这么多谓词:contains()

matches( //*[self::p or self::div][matches(text(),'(apples|oranges|bananas)'])

最后,请注意在 XPath 中使用//and*效率非常低,如果您的文档对它有任何影响,您将看到性能影响。我有一种痒,告诉我有办法优化它,但不幸的是我没有时间研究。

于 2013-07-16T22:47:23.447 回答