0

使用 CsQuery 我需要修改一组锚元素,例如

'...

Dim cqContext = WebForms.CreateFromRender(Page, AddressOf MyBase.Render, writer)

Dim cq = cqContext.Dom

Dim foo = cq("a")

'...

例如,在所有锚元素上,我需要将 href 开头的“/MyFolderName/”替换为“../”。

我可以简单地这样做:

For Each i In cq("a")
    i.Attributes("href") = Regex.Replace(i.Attributes("href"), "^/MyFolderName/", "../", RegexOptions.IgnoreCase)
Next

还是使用each实用程序方法更有效?

我还应该将选择器缩小到cq("a[href^=""/MyFolderName/""]")吗?

还是有更好的方法?

编辑:高效我不仅仅意味着最便宜,我还在寻找更优雅的方式,例如更少的代码/更少的操作方式。

具体来说:

  • 我应该使用each实用程序方法吗?
  • 我应该像上面那样缩小我的选择器吗?
4

2 回答 2

1

在问这个问题时,有一个隐含的假设,即您已经实施了其中一个解决方案,并且通过检测发现它是不可接受的减速的根源。如果你还没有这样做,我会听从 Donald Knuth 的意见:

过早的优化是万恶之源。

于 2013-07-30T16:34:33.057 回答
1

从 CsQuery 在这里实现问题的方式来看:

  1. 使用forvsEach不会产生实质性的影响。

  2. 使用cq("a[href^='MyFolderName']")可能与您编码的方法不同,但这仅仅是因为 CsQuery 以不同的方式实现子字符串搜索。CsQuery 使用索引来根据类、id、属性名称和标签名称的选择器来定位元素,这部分非常快。但是子字符串搜索仍然是老式的方式,a必须扫描每个节点以查看它是否与子字符串匹配。代码在这里

            case AttributeSelectorType.Contains:
                return value != null && value.IndexOf(selector.AttributeValue,
                    selector.AttributeValueStringComparison)>=0;
    

所以真正的问题是,它indexOf比正则表达式搜索和替换更快。(我的猜测?可能,因为它是一种单一用途的方法。)

但归根结底,我也同意关于过早优化的评论。只要可以通过选择器语法,我更愿意编写选择器来准确定位您想要的:

cq("a[href^='MyFolderName']")

因为它富有表现力和紧凑。如果由于某种原因,选择器语法比使用其他方法来缩小选择范围超出 CsQuery 索引的范围要慢得多,那么您以后可以随时更改它。

还有一个基于 James Padolsey 的 jQuery 扩展内置的正则表达式选择器,有关描述和用法,请参阅此博客文章。我希望这与您的方法大致相同:)

最后:到目前为止,在大多数情况下,CsQuery 将花费的最多时间是首先解析您的文档。与最初仅使用 CsQuery 相比,此后您所做的任何事情都不太可能对性能产生重大影响。但是,如果您发现这很重要,那么您也有选择,有可用的索引策略的替代实现可以针对您打算在解析后使用文档的方式。

于 2013-07-30T20:45:21.583 回答