尝试组装正确的XSLT代码以分配公共ID,该ID从递归链的最低成员(从其“ uniq-id”中获取)分配给上述所有元素。无法获得祖先的节点。
源xml
<root>
<Object id="top" uniq-id="001" status="0" rank="1"/>
<Object id="middle" id-parent="top" uniq-id="020" status="0" rank="3"/>
<Object id="middle" id-parent="top" uniq-id="021" status="1" rank="3"/>
<!-- only the element with status="0" is considered -->
<Object id="bottom-1" id-parent="middle" uniq-id="111" status="1" rank="6" />
<Object id="bottom-2" id-parent="middle" uniq-id="222" status="1" rank="6" />
<Object id="bottom-3" id-parent="middle" uniq-id="333" status="0" rank="6" /> <!-- will be taken -->
<Object id="bottom-4" id-parent="middle" uniq-id="444" status="1" rank="6" />
<Object id="bottom-5" id-parent="middle" uniq-id="555" status="1" rank="7" />
<Object id="bottom-6" id-parent="middle" uniq-id="666" status="0" rank="7" /> <!-- will be taken -->
<Object id="bottom-7" id-parent="middle" uniq-id="777" status="1" rank="6" />
<Object id="bottom-8" id-parent="middle" uniq-id="888" status="1" rank="6" />
<Object id="bottom-9" id-parent="middle" uniq-id="999" status="0" rank="6" /> <!-- will be taken -->
</root>
起始xslt
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exslt="http://exslt.org/common">
<xsl:key name="Object-By-id" match="Object[(@status='0')]" use="@id"/>
<xsl:key name="Object-By-id-parent" match="Object[(@status='0')]" use="string(@id-parent)"/>
<xsl:variable name="fold-rtf">
<xsl:apply-templates select="/" mode="fold"/>
</xsl:variable>
<xsl:variable name="folded-tree" select="exslt:node-set($fold-rtf)"/>
<xsl:template match="@*|node()[(@status='0')]">
<xsl:copy>
<xsl:apply-templates select="@* | node()[(@status='0')]"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Object[@status=0]/@*[last()]">
<xsl:variable name="current" select=".."/>
<xsl:copy/>
<xsl:for-each select="$folded-tree">
<xsl:for-each select="key('Object-By-id',$current/@id)">
<!-- ====== !! =======-->
<xsl:if test="position()!=last()">
<xsl:for-each select="ancestor-or-self::*">
<xsl:attribute name="chain-id">
<xsl:value-of select="@uniq-id"/>
</xsl:attribute>
</xsl:for-each>
</xsl:if>
<!-- ======= !! =======-->
</xsl:for-each>
</xsl:for-each>
</xsl:template>
<xsl:template match="/|*" mode="fold">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:apply-templates select="key('Object-By-id-parent',string(@id))" mode="fold">
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
结果(不正确)https://xsltfiddle.liberty-development.net/94Acsm2/1
假定的输出
<root>
<Object id="top" uniq-id="001" status="0" rank="1" chain-id="20"/>
<Object id="middle" id-parent="top" uniq-id="020" status="0" rank="3" chain-id="20"/>
<Object id="bottom-3" id-parent="middle" uniq-id="333" status="0" rank="6" chain-id="333"/>
<Object id="middle" id-parent="top" uniq-id="020" status="0" rank="3" chain-id="333"/>
<Object id="top" uniq-id="001" status="0" rank="1" chain-id="333"/>
<Object id="bottom-6" id-parent="middle" uniq-id="666" status="0" rank="7" chain-id="666"/>
<Object id="middle" id-parent="top" uniq-id="020" status="0" rank="3" chain-id="666"/>
<Object id="top" uniq-id="001" status="0" rank="1" chain-id="666"/>
<Object id="bottom-9" id-parent="middle" uniq-id="999" status="0" rank="6" chain-id="999"/>
<Object id="middle" id-parent="top" uniq-id="020" status="0" rank="3" chain-id="999"/>
<Object id="top" uniq-id="001" status="0" rank="1" chain-id="999"/>
</root>
欢迎您使用所有解决方案来改进XSLT代码
从非工作代码中对需求进行逆向工程总是很困难,但是我认为您要尝试的是使用来选择元素@status="0"
,并为每个元素显示逻辑祖先,即关系的递归扩展parent(X)
,其中parent(X)
选择@id等于的元素X/@parent-id
。
自从我用XSLT 1.0编码以来已经很长时间了(现在已经被取代很长时间了……),如果我犯任何错误,我们深表歉意。
首先定义一个通过id选择对象的键:
<xsl:key name="by-id" match="Object" use="@id"/>
现在定义一个递归模板以打印节点的逻辑祖先:
<xsl:template match="Object" mode="ancestors">
<xsl:copy-of select="."/>
<xsl:apply-templates select="key('by-id', @parent-id)" mode="ancestors"/>
</xsl:template>
现在为选定的项目调用它:
<xsl:template match="/">
<root>
<xsl:apply-templates select="root/Object[@status='0']" mode="ancestors"/>
</root>
</xsl:template>
未经测试。
谢谢迈克尔!我会尽快实施。
决定仅依靠您的代码来制作新程序集。该算法实际上根据status =“ 0”确定链中“最低”的元素,但是并没有走得更远(实际上,这是本集的真正MacGuffin)。 xsltfiddle.liberty-development.net/pPJ9hEf
我这次要实现的主要目的不是要从上到下的方向说明组装的链,而是要以相反的顺序现在重新组装,其中每个父元素a)复制b)(主选项!)-获得一个新的公共属性“ chain-id”,其值将从“下部元素”的“ uniq-id”中获取(此处用“ 333”,“ 666”表示, “ 999”值)互连方案(基本)imgur.com/p868Xqc互连输出方案 imgur.com/PRDYvyo
从使用XSLT的一些经验中,我可以假定解决方案仅次于使用XSLT-lexem,例如“ position”和“ last”。粗略地说,当对象元素的“位置”为“最后”时,反向重建及其说明就开始发生。
我看过像Novachev的方法stackoverflow.com/questions/58101443/…之类的资源,但是尽管这些知识提供了很多积木,甚至不了解应该发生什么的形式逻辑,但我仍无法弄清楚如何将其带入工作代码。