【发布时间】:2020-01-31 10:20:26
【问题描述】:
尝试组装正确的 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 代码的所有解决方案
【问题讨论】:
-
我不得不承认我已经多次阅读了您的描述,并查看了输入和假定的输出 xml,但我不明白您要做什么,我的意思是我理解您正在尝试从输入中获取假定的输出,但我不了解假定输出中的元素如何相互关联的逻辑。希望您能澄清这个问题,以防其他人有同样的问题。
-
/@*[last()]没有任何意义。您要求的是最后一个属性,但属性的顺序是完全不可预测的。 -
to user254694 - 这个描述可能与前面的类似,但这个问题非常具体和新颖。它还依赖于源 XML,即递归(是的,递归的存在将我最近的所有问题结合在一起。这件事不是最简单的,所以我必须修改它)。顺便说一句,在我认为的所有内容中 - 这个对主要条件\问题非常清楚('从最低成员那里获得所有祖先的共同 id')。换个说法?我会试试的。
-
所有之前的请求,一般来说,都针对一个方向 - 解开整个互连元素链,恢复它们并以某种方式明确它们在人类逻辑和感知中的可读性。
-
如果我们继续用人类逻辑(空间和时间)来描述——当前问题实际上是之前递归算法保留的地方的延续。 1- step - 我们找到递归链的“末端”。 2 - 现在你需要“遍历”这条链,现在知道“较低”元素的 uniq-id 值 - 以相反的顺序(从下到上)将其值分配给所有元素(至少现在我认为可能的算法的抽象逻辑就是这样。战术问题是要知道如何在特定的 xslt 代码中表示这种抽象。