Xslt 计算每个节点的Strahler数
节点的长度 在树中是节点高度概念的推广 目标是定义一个转换,该转换向XML文档的每个节点添加一个数字属性,例如Xslt 计算每个节点的Strahler数,xslt,xquery,Xslt,Xquery,节点的长度 在树中是节点高度概念的推广 目标是定义一个转换,该转换向XML文档的每个节点添加一个数字属性,例如strahler 归纳地,节点的Strahler数n,表示为Stn(n),定义如下: 如果n是一片叶子,那么Stn(n)=0 else(n不是叶)通过降低Strahler值对其子项(n1,…,nd)排序:Stn(n1)≥ Stn(n2)≥ ... ≥ Stn(nd)。 如果Stn(n1)=Stn(n2)那么Stn(n)=n1+1;否则Stn(n)=Stn(n1) 例如,对于节点n和
strahler
归纳地,节点的Strahler数n
,表示为Stn(n)
,定义如下:
- 如果
是一片叶子,那么n
Stn(n)=0
- else(
不是叶)通过降低Strahler值对其子项(n
,…,n1
)排序:nd
≥ <代码>Stn(n2)≥ ... ≥Stn(n1)
。 如果Stn(nd)
那么Stn(n1)=Stn(n2)
;否则Stn(n)=n1+1
李>Stn(n)=Stn(n1)
n
和子节点n1
n2
n3
和Stn1
2
3
,n
的Stn分别为3
(因为最大值只出现一次)。对于带有子节点n1
n2
n3
和Stn1
2
2
的节点n
的Stn分别为3
(因为最大值出现了不止一次)
样本输入:
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<root strahler="2" field="4">
<a strahler="2">
<aa strahler="0" x="1"/>
<ab strahler="2">
<aba strahler="1" number="36" usefulness="useful">
<abaa strahler="0">text1</abaa>
<abab strahler="0">
<ababa strahler="0">text2</ababa>
</abab>
</aba>
<abb strahler="1" number="37" usefulness="useful">
<abba strahler="0">text3</abba>
<abbb strahler="1">
<abbba strahler="0">text4</abbba>
<abbbb strahler="0">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" saxon:memo-function="yes">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"if(not($pElem/*))
then 1
else
if(not($pElem/*[2]))
then f:strahler($pElem/*[1])
else for $maxVal in max($pElem/*/f:strahler(.)),
$twoWithMax in
(($pElem/*[f:strahler(.) eq $maxVal])[2]/1, 0)[1]
return $maxVal+$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" cache="full">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"let $children := $pElem/*
return
if(not($children))
then 1
else
if(not($children[2]))
then f:strahler($children[1])
else
let $childrenStrahler := $children/f:strahler(.),
$maxVal := max($childrenStrahler),
$twoWithMax := ($childrenStrahler[. eq $maxVal][2]!1, 0)[1]
return $maxVal +$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
文本1
文本2
文本3
文本4
文本5
输出:
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<root strahler="2" field="4">
<a strahler="2">
<aa strahler="0" x="1"/>
<ab strahler="2">
<aba strahler="1" number="36" usefulness="useful">
<abaa strahler="0">text1</abaa>
<abab strahler="0">
<ababa strahler="0">text2</ababa>
</abab>
</aba>
<abb strahler="1" number="37" usefulness="useful">
<abba strahler="0">text3</abba>
<abbb strahler="1">
<abbba strahler="0">text4</abbba>
<abbbb strahler="0">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" saxon:memo-function="yes">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"if(not($pElem/*))
then 1
else
if(not($pElem/*[2]))
then f:strahler($pElem/*[1])
else for $maxVal in max($pElem/*/f:strahler(.)),
$twoWithMax in
(($pElem/*[f:strahler(.) eq $maxVal])[2]/1, 0)[1]
return $maxVal+$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" cache="full">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"let $children := $pElem/*
return
if(not($children))
then 1
else
if(not($children[2]))
then f:strahler($children[1])
else
let $childrenStrahler := $children/f:strahler(.),
$maxVal := max($childrenStrahler),
$twoWithMax := ($childrenStrahler[. eq $maxVal][2]!1, 0)[1]
return $maxVal +$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
文本1
文本2
文本3
文本4
文本5
XSLT不太可能是实现这一点的最佳工具,主要是因为它无法真正从下至上遍历树。从最深的层次开始,可以一次将Strahler数添加到树的一个层次,但是每次都必须重新处理整个树,这导致了一个非常低效的算法
不过,如果没有其他方法,您可以尝试以下方法:
XSLT2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:variable name="max-depth" select="max(//*/count(ancestor::node()))"/>
<xsl:template match="/">
<xsl:call-template name="strahler">
<xsl:with-param name="node-set" select="*"/>
<xsl:with-param name="current-level" select="$max-depth"/>
</xsl:call-template>
</xsl:template>
<xsl:template name="strahler">
<xsl:param name="node-set" select="*"/>
<xsl:param name="current-level"/>
<xsl:variable name="next-set">
<xsl:apply-templates select="$node-set" mode="strahler">
<xsl:with-param name="current-level" select="$current-level"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:choose>
<xsl:when test="$current-level > 1">
<!-- recursive call -->
<xsl:call-template name="strahler">
<xsl:with-param name="node-set" select="$next-set"/>
<xsl:with-param name="current-level" select="$current-level - 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="$next-set"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="strahler">
<xsl:param name="current-level"/>
<xsl:copy>
<xsl:if test="count(ancestor::node()) = $current-level">
<xsl:attribute name="strahler">
<xsl:variable name="max-strahler" select="max(*/@strahler)" />
<xsl:choose>
<xsl:when test="not(*)">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:when test="count(*[@strahler=$max-strahler]) > 1">
<xsl:value-of select="$max-strahler + 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$max-strahler"/>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:copy-of select="@*"/>
<xsl:apply-templates mode="strahler">
<xsl:with-param name="current-level" select="$current-level"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
应用于输入示例,结果将是:
<?xml version="1.0" encoding="UTF-8"?>
<root strahler="3" field="4">
<a strahler="3">
<aa strahler="1" x="1"/>
<ab strahler="3">
<aba strahler="2" number="36" usefulness="useful">
<abaa strahler="1">text1</abaa>
<abab strahler="1">
<ababa strahler="1">text2</ababa>
</abab>
</aba>
<abb strahler="2" number="37" usefulness="useful">
<abba strahler="1">text3</abba>
<abbb strahler="2">
<abbba strahler="1">text4</abbba>
<abbbb strahler="1">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
文本1
文本2
文本3
文本4
文本5
这与您发布的结果不同,但根据您链接到的维基百科文章中的规则,我相信这是正确的
请注意,“高度”在这里没有用处。这是一个简短而高效的XSLT 2.0转换:
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<root strahler="2" field="4">
<a strahler="2">
<aa strahler="0" x="1"/>
<ab strahler="2">
<aba strahler="1" number="36" usefulness="useful">
<abaa strahler="0">text1</abaa>
<abab strahler="0">
<ababa strahler="0">text2</ababa>
</abab>
</aba>
<abb strahler="1" number="37" usefulness="useful">
<abba strahler="0">text3</abba>
<abbb strahler="1">
<abbba strahler="0">text4</abbba>
<abbbb strahler="0">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" saxon:memo-function="yes">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"if(not($pElem/*))
then 1
else
if(not($pElem/*[2]))
then f:strahler($pElem/*[1])
else for $maxVal in max($pElem/*/f:strahler(.)),
$twoWithMax in
(($pElem/*[f:strahler(.) eq $maxVal])[2]/1, 0)[1]
return $maxVal+$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" cache="full">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"let $children := $pElem/*
return
if(not($children))
then 1
else
if(not($children[2]))
then f:strahler($children[1])
else
let $childrenStrahler := $children/f:strahler(.),
$maxVal := max($childrenStrahler),
$twoWithMax := ($childrenStrahler[. eq $maxVal][2]!1, 0)[1]
return $maxVal +$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
使用XSLT 3.0/XPath 3.0实现更紧凑、更高效的解决方案:
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<root strahler="2" field="4">
<a strahler="2">
<aa strahler="0" x="1"/>
<ab strahler="2">
<aba strahler="1" number="36" usefulness="useful">
<abaa strahler="0">text1</abaa>
<abab strahler="0">
<ababa strahler="0">text2</ababa>
</abab>
</aba>
<abb strahler="1" number="37" usefulness="useful">
<abba strahler="0">text3</abba>
<abbb strahler="1">
<abbba strahler="0">text4</abbba>
<abbbb strahler="0">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" saxon:memo-function="yes">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"if(not($pElem/*))
then 1
else
if(not($pElem/*[2]))
then f:strahler($pElem/*[1])
else for $maxVal in max($pElem/*/f:strahler(.)),
$twoWithMax in
(($pElem/*[f:strahler(.) eq $maxVal])[2]/1, 0)[1]
return $maxVal+$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" cache="full">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"let $children := $pElem/*
return
if(not($children))
then 1
else
if(not($children[2]))
then f:strahler($children[1])
else
let $childrenStrahler := $children/f:strahler(.),
$maxVal := max($childrenStrahler),
$twoWithMax := ($childrenStrahler[. eq $maxVal][2]!1, 0)[1]
return $maxVal +$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
效率:
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<root strahler="2" field="4">
<a strahler="2">
<aa strahler="0" x="1"/>
<ab strahler="2">
<aba strahler="1" number="36" usefulness="useful">
<abaa strahler="0">text1</abaa>
<abab strahler="0">
<ababa strahler="0">text2</ababa>
</abab>
</aba>
<abb strahler="1" number="37" usefulness="useful">
<abba strahler="0">text3</abba>
<abbb strahler="1">
<abbba strahler="0">text4</abbba>
<abbbb strahler="0">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" saxon:memo-function="yes">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"if(not($pElem/*))
then 1
else
if(not($pElem/*[2]))
then f:strahler($pElem/*[1])
else for $maxVal in max($pElem/*/f:strahler(.)),
$twoWithMax in
(($pElem/*[f:strahler(.) eq $maxVal])[2]/1, 0)[1]
return $maxVal+$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" cache="full">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"let $children := $pElem/*
return
if(not($children))
then 1
else
if(not($children[2]))
then f:strahler($children[1])
else
let $childrenStrahler := $children/f:strahler(.),
$maxVal := max($childrenStrahler),
$twoWithMax := ($childrenStrahler[. eq $maxVal][2]!1, 0)[1]
return $maxVal +$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
XSLT不太可能是这方面的最佳工具 如果有人告诉你这些,不要相信他们 通过使用记忆功能,两种解决方案都是有效的 事实上,
f:stahler($阳极)
对于每个不同的元素只计算一次
请注意使用:
saxon:memo function=“yes”
cache=“full”
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<root strahler="2" field="4">
<a strahler="2">
<aa strahler="0" x="1"/>
<ab strahler="2">
<aba strahler="1" number="36" usefulness="useful">
<abaa strahler="0">text1</abaa>
<abab strahler="0">
<ababa strahler="0">text2</ababa>
</abab>
</aba>
<abb strahler="1" number="37" usefulness="useful">
<abba strahler="0">text3</abba>
<abbb strahler="1">
<abbba strahler="0">text4</abbba>
<abbbb strahler="0">text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:saxon="http://saxon.sf.net/"
xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" saxon:memo-function="yes">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"if(not($pElem/*))
then 1
else
if(not($pElem/*[2]))
then f:strahler($pElem/*[1])
else for $maxVal in max($pElem/*/f:strahler(.)),
$twoWithMax in
(($pElem/*[f:strahler(.) eq $maxVal])[2]/1, 0)[1]
return $maxVal+$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
<root field="4">
<a>
<aa x="1"/>
<ab>
<aba number="36" usefulness="useful">
<abaa>text1</abaa>
<abab>
<ababa>text2</ababa>
</abab>
</aba>
<abb number="37" usefulness="useful">
<abba>text3</abba>
<abbb>
<abbba>text4</abbba>
<abbbb>text5</abbbb>
</abbb>
</abb>
</ab>
</a>
</root>
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:f="my:f">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[true()]">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:attribute name="strahler" select="f:strahler(.)"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:function name="f:strahler" as="xs:integer" cache="full">
<xsl:param name="pElem" as="element()"/>
<xsl:sequence select=
"let $children := $pElem/*
return
if(not($children))
then 1
else
if(not($children[2]))
then f:strahler($children[1])
else
let $childrenStrahler := $children/f:strahler(.),
$maxVal := max($childrenStrahler),
$twoWithMax := ($childrenStrahler[. eq $maxVal][2]!1, 0)[1]
return $maxVal +$twoWithMax
"/>
</xsl:function>
</xsl:stylesheet>
值cache=“full”鼓励处理器保留
在同一转换期间此函数的所有以前调用,以及
尽可能重用此内存中的结果。价值
cache=“partial”鼓励处理器保留此类内存,但
如有必要,丢弃结果以保持内存使用量在
界限。默认值cache=“no”鼓励处理器不要
保留以前通话的记忆
XSLT很适合这项工作,Dimitre的解决方案非常完美(+1) 以下是中的替代实现的外观:
declare function local:strahler($nodes as node()*) as node()*
{
for $node in $nodes
return
typeswitch ($node)
case document-node() return
document {local:strahler($node/node())}
case element() return
element {node-name($node)}
{
let $children := local:strahler($node/node())
let $max := (max($children/@strahler), 1)[1]
return
(
$node/@*,
attribute strahler {$max + (($children/@strahler[. = $max])[2]/1, 0)[1]},
$children
)
}
default return
$node
};
local:strahler(.)
当将其放入文件strahler.xq
,并在sample.xml
中输入时,可以使用以下命令从命令行运行:
java net.sf.saxon.Query strahler.xq -s:sample.xml
与XSLT变体一样,它在自下而上添加新属性的同时重写文档。这里的重写比XSLT更明显,但是在本例中XSLT已经足够了。我想谦虚地建议重新格式化这个问题,这样您就可以得到正确的回答。据我所知,您询问的内容还不清楚。如果您包含最小的一组示例XML来说明您的问题,再加上所需的输出、当前XSLT代码、当前输出以及您对问题的想法,您就更有可能得到响应。祝你好运。当你说:“n的Stn等于n1+1的Stn”第三个Stn是什么?我把它理解为stn(n)=stn(n+1)^stn(其中^表示“的幂”),但stn不是一个数字,它是一个函数。事实上,我找不到任何关于你的规则的解释