说我有一棵这样的树(但实际上,有成千上万个节点,例如HTML文档):
a
____________|____________
| |
b f
____________| ____|____
| | | |
c m x y
____|____ __|__ |
| | | | | | w
d e r s q u
|
t
我想使用这种“树正则表达式”查询子树(其中*表示跳过节点,字母是节点标签或标记):
__ __ __ __
/ \ / \
| a | | a a a |
| / \ | | / \ | / \ |
| b f | | b f z * f |
| | | OR | | AND AND / \ \ |
| c | | x n o w |
| / \ | | | |
| d e | | p |
\__ __/ \__ __/
想知道XSLT,XQuery,XPath,CSS选择器或类似的东西是否可以执行这样的查询。如果是这样,它将如何在高水平上完成。我只是很快地写出了这个示例,而没有真正考虑它是否会很好地工作,因此也许仅尝试部分查询(例如第一个块或最后一个块)会很困难。
更新
这与示例HTML文档中的图片几乎相同:
<a>
<b id="foo">
<c>
<d id="bar"></d>
<e></e>
<r></r>
<s>
<t></t>
</s>
</c>
<m>
<q></q>
<u></u>
</m>
</b>
<f id="baz">
<x></x>
<y>
<w></w>
</y>
</f>
</a>
这将是与之匹配的模式:
<a>
<b>
<c>
<d></d>
<e></e>
</c>
</b>
<f></f>
</a>
这将是输出:
<a>
<b id="foo">
<c>
<d id="bar"></d>
<e></e>
</c>
</b>
<f id="baz"></f>
</a>
或者这个,要么:
<a>
<b id="foo">
<c>
<d id="bar"></d>
<e></e>
</c>
</b>
<f id="baz">
<x></x>
<y>
<w></w>
</y>
</f>
</a>
答案 0 :(得分:2)
在https://xsltfiddle.liberty-development.net/eiZQaFo/1,我尝试实现注释中的建议,即使用XSLT 3将显示的“模式”树(作为参数提供)转换为XSLT 3样式表,然后应用于使用XPath 3.1 transform
函数显示的原始输入树时,XSLT是
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:axsl="http://www.w3.org/1999/XSL/Transform-alias"
version="3.0">
<xsl:namespace-alias stylesheet-prefix="axsl" result-prefix="xsl"/>
<xsl:output indent="yes"/>
<xsl:param name="pattern-tree">
<a>
<b>
<c>
<d></d>
<e></e>
</c>
</b>
<f></f>
</a>
</xsl:param>
<xsl:variable name="stylesheet">
<axsl:stylesheet version="3.0">
<axsl:mode on-no-match="deep-skip"/>
<axsl:template match="{string-join($pattern-tree//*!string-join(ancestor-or-self::*/name(), '/'), ' | ')}">
<axsl:copy>
<axsl:apply-templates select="@* | node()"/>
</axsl:copy>
</axsl:template>
<axsl:template match="@*">
<axsl:copy/>
</axsl:template>
</axsl:stylesheet>
</xsl:variable>
<xsl:template match="/">
<xsl:copy-of select="$stylesheet"/>
<xsl:sequence select="transform(map { 'source-node' : /, 'stylesheet-node' : $stylesheet })?output"/>
</xsl:template>
</xsl:stylesheet>
有输出(为进行调试和解释,它包含生成的XSLT,但是您当然可以删除/注释<xsl:copy-of select="$stylesheet"/>
)
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:mode on-no-match="deep-skip"/>
<xsl:template match="a | a/b | a/b/c | a/b/c/d | a/b/c/e | a/f">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="@*">
<xsl:copy/>
</xsl:template>
</xsl:stylesheet>
<a>
<b id="foo">
<c>
<d id="bar"/>
<e/>
</c>
</b>
<f id="baz"/>
</a>