Xml 我可以让xpath搜索更快吗?
找到所有Xml 我可以让xpath搜索更快吗?,xml,xpath,php-5.2,Xml,Xpath,Php 5.2,找到所有 是上下文元素的后代 具有auto属性 最高级别(在self和上下文元素之间没有具有auto属性的祖先) 因此,如果上下文节点是a,则应返回c和e 我已经在我的php类中实现了它: $tempId='XDFAY69LA'; $this->setAttribute('tempId',$tempId); $path=“../\*[@auto and not(祖先:\*[@auto and祖先::\*[@tempId='$tempId']])”; $ar=$this->getElementsB
auto
属性auto
属性的祖先)a
,则应返回c
和e
我已经在我的php类中实现了它:
$tempId='XDFAY69LA';
$this->setAttribute('tempId',$tempId);
$path=“../\*[@auto and not(祖先:\*[@auto and祖先::\*[@tempId='$tempId']])”;
$ar=$this->getElementsByXPath($path);
$this->removeAttribute('tempId');
但是我发现这个查询很慢,也许,因为查询太复杂了,有没有更好的方法
我写了一个测试,请看一下:
我想把它简化一点
$path=".//*[@auto and not(ancestor::*[@auto and not(@tempId='$tempId'))]";
“祖先::*[@tempId='$tempId']”
到
“不是(@tempId='$tempId')”
//编辑内容:从XPath开始删除冗长的内容:
.//*[@auto and not(ancestor::*[@auto and ancestor::*[@tempId='$tempId']])]
那么:
.//*[@auto and not(ancestor::*[@auto][ancestor::*[@tempId='$tempId']])]
甚至
.//*[@auto and count(ancestor::*[@auto][ancestor::*[@tempId='$tempId']])=0]
使用:
.//*[@auto and $tempId = ancestor::*[@auto][1]/@tempId]
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="a">
<xsl:variable name="tempId" select="@tempId"/>
<xsl:copy-of select=
".//*[@auto and $tempId = ancestor::*[@auto][1]/@tempId]"/>
</xsl:template>
</xsl:stylesheet>
<root>
<a auto="1" tempId="current">
<b>
<c auto="1">
<d auto="1"></d>
</c>
</b>
<e auto="1">
<f>
<g auto="1"></g>
</f>
</e>
</a>
</root>
<c auto="1">
<d auto="1"/>
</c>
<e auto="1">
<f>
<g auto="1"/>
</f>
</e>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kfirstDescendents" match="*[@auto]"
use="generate-id(ancestor::*[@auto][1])"/>
<xsl:template match="a">
<xsl:copy-of select=
"key('kfirstDescendents', generate-id())"/>
</xsl:template>
</xsl:stylesheet>
这将选择具有auto
属性且其具有auto
属性的第一个祖先也具有与上下文节点的tempId
属性值相同的tempId>属性的(上下文节点的)所有子代元素(后者存储在$tempId
变量中)
这里我们假设没有两个不同的元素具有相同的tempId
属性值
基于XSLT的快速验证:
.//*[@auto and $tempId = ancestor::*[@auto][1]/@tempId]
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="a">
<xsl:variable name="tempId" select="@tempId"/>
<xsl:copy-of select=
".//*[@auto and $tempId = ancestor::*[@auto][1]/@tempId]"/>
</xsl:template>
</xsl:stylesheet>
<root>
<a auto="1" tempId="current">
<b>
<c auto="1">
<d auto="1"></d>
</c>
</b>
<e auto="1">
<f>
<g auto="1"></g>
</f>
</e>
</a>
</root>
<c auto="1">
<d auto="1"/>
</c>
<e auto="1">
<f>
<g auto="1"/>
</f>
</e>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kfirstDescendents" match="*[@auto]"
use="generate-id(ancestor::*[@auto][1])"/>
<xsl:template match="a">
<xsl:copy-of select=
"key('kfirstDescendents', generate-id())"/>
</xsl:template>
</xsl:stylesheet>
性能不能仅在XPath表达式中改进,效率低下是因为必须使用/
XPath伪运算符
如果使用XSLT,则可以使用键获得有效的解决方案:
.//*[@auto and $tempId = ancestor::*[@auto][1]/@tempId]
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="a">
<xsl:variable name="tempId" select="@tempId"/>
<xsl:copy-of select=
".//*[@auto and $tempId = ancestor::*[@auto][1]/@tempId]"/>
</xsl:template>
</xsl:stylesheet>
<root>
<a auto="1" tempId="current">
<b>
<c auto="1">
<d auto="1"></d>
</c>
</b>
<e auto="1">
<f>
<g auto="1"></g>
</f>
</e>
</a>
</root>
<c auto="1">
<d auto="1"/>
</c>
<e auto="1">
<f>
<g auto="1"/>
</f>
</e>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kfirstDescendents" match="*[@auto]"
use="generate-id(ancestor::*[@auto][1])"/>
<xsl:template match="a">
<xsl:copy-of select=
"key('kfirstDescendents', generate-id())"/>
</xsl:template>
</xsl:stylesheet>
此转换产生与第一次相同的结果,并且在包含许多嵌套元素且具有auto
属性的文档上大大加快
如果完全排除使用XSLT,那么使用哈希表(对不起,我不知道PHP)可以达到与XSLT键相同的效果.非常感谢,但我认为这一个与我的不一样,也不是有效的xpath表达式。我是盲人。如果“a”的祖先具有“@auto”属性,则我的代码不匹配,对不起。请放心,我在这个问题上也犯了很多错误。谢谢。好问题,+1。有关较短的xpath表达式和muc的演示,请参阅我的答案h使用XSLT和键实现更快的解决方案。如果禁止使用XSLT,可以使用哈希表实现类似的解决方案。非常感谢,这教会了我一种新的xpathYeah!我喜欢你的表达式,尽管它似乎没有像你说的那样提高速度。我没有使用XSLT,但我认为我需要了解它以及你对哈希表的建议现在,感谢您的回复!@fclddcn:我从来没有说过表达式是快的——相反,我说它很慢,而且获得更快执行的唯一方法是通过缓存(索引、xslt键、哈希表等)。我明白了,很抱歉我的英语不好,我的意思是“和您说的一样”: