标记树中的叶节点 (XSLT 1.0)
labeling leaf nodes in tree (XSLT 1.0)
我有一个xml,我想处理,然后简单地依次标记每个叶节点,翻转或翻转,除非满足某些条件。
以这个为例xml
<root>
<tx>
<alloc>
<event>a</event>
<event>b</event>
</alloc>
<alloc>
<event>c</event>
<event>d</event>
<event>d1</event>
</alloc>
</tx>
<tx>
<alloc>
<event>e</event>
<event>f</event>
<event>g</event>
</alloc>
</tx>
</root>
假设我们想要标记每个事件节点,翻转然后翻转然后翻转,等等除非事件是“e”
请注意,事件的标签独立于层次结构。
所以...
<root>
<tx>
<alloc>
<event flip="true">a</event>
<event flip="false">b</event>
</alloc>
<alloc>
<event flip="true">c</event>
<event flip="false">d</event>
<event flip="true">d1</event>
</alloc>
</tx>
<tx>
<alloc>
<event flip="true">e</event>
<event flip="false">f</event>
<event flip="true">g</event>
</alloc>
</tx>
</root>
所以根据我们的规则,节点“d1”为“真”且“e”在继续之前保持为“真”。
现在...我可以找到一种方法来做到这一点,但感觉它不太适合 XSLT。
如果我用某种函数式语言来做这件事,我会递归处理树,基本上是克隆它,通过每个递归函数传递 flip/flop 的值,所以像...
所以例如 tx 处理模板看起来像这样(这是编造的)
<xsl:template match="tx" mode="label">
<xsl:param name="flip_flip"/>
<xsl:variable name="allocations">
<xsl:apply-templates select="alloc" mode="label">
<xsl:with-param name="flip_flip" select="$flip_flop"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="$allocations"/>
<xsl:variable name="new_flip_flip" select="alloc/event/@flip[last()]"
<xsl:apply-templates select="following-sibling::tx[1]" mode="label">
<xsl:with-param name="flip_flip" select="$new_flip_flip + 1"/>
</xsl:apply-templates>
</xsl:template>
即依次处理每个元素,拉出上次计算的触发器值,然后处理下一个。
感觉xslt很丑
另一种选择是计算前面发生的事件的数量,减去异常的数量,然后计算出 mod 2 flip 是真还是假。
再次,感觉笨重,计算量大。
这样的东西对你有用吗:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="event">
<xsl:variable name="i">
<xsl:number count="event[not(.='e')]" level="any" />
</xsl:variable>
<event flip="{boolean($i mod 2)}">
<xsl:apply-templates/>
</event>
</xsl:template>
</xsl:stylesheet>
我有一个xml,我想处理,然后简单地依次标记每个叶节点,翻转或翻转,除非满足某些条件。
以这个为例xml
<root>
<tx>
<alloc>
<event>a</event>
<event>b</event>
</alloc>
<alloc>
<event>c</event>
<event>d</event>
<event>d1</event>
</alloc>
</tx>
<tx>
<alloc>
<event>e</event>
<event>f</event>
<event>g</event>
</alloc>
</tx>
</root>
假设我们想要标记每个事件节点,翻转然后翻转然后翻转,等等除非事件是“e”
请注意,事件的标签独立于层次结构。
所以...
<root>
<tx>
<alloc>
<event flip="true">a</event>
<event flip="false">b</event>
</alloc>
<alloc>
<event flip="true">c</event>
<event flip="false">d</event>
<event flip="true">d1</event>
</alloc>
</tx>
<tx>
<alloc>
<event flip="true">e</event>
<event flip="false">f</event>
<event flip="true">g</event>
</alloc>
</tx>
</root>
所以根据我们的规则,节点“d1”为“真”且“e”在继续之前保持为“真”。
现在...我可以找到一种方法来做到这一点,但感觉它不太适合 XSLT。
如果我用某种函数式语言来做这件事,我会递归处理树,基本上是克隆它,通过每个递归函数传递 flip/flop 的值,所以像...
所以例如 tx 处理模板看起来像这样(这是编造的)
<xsl:template match="tx" mode="label">
<xsl:param name="flip_flip"/>
<xsl:variable name="allocations">
<xsl:apply-templates select="alloc" mode="label">
<xsl:with-param name="flip_flip" select="$flip_flop"/>
</xsl:apply-templates>
</xsl:variable>
<xsl:copy-of select="$allocations"/>
<xsl:variable name="new_flip_flip" select="alloc/event/@flip[last()]"
<xsl:apply-templates select="following-sibling::tx[1]" mode="label">
<xsl:with-param name="flip_flip" select="$new_flip_flip + 1"/>
</xsl:apply-templates>
</xsl:template>
即依次处理每个元素,拉出上次计算的触发器值,然后处理下一个。
感觉xslt很丑
另一种选择是计算前面发生的事件的数量,减去异常的数量,然后计算出 mod 2 flip 是真还是假。 再次,感觉笨重,计算量大。
这样的东西对你有用吗:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="event">
<xsl:variable name="i">
<xsl:number count="event[not(.='e')]" level="any" />
</xsl:variable>
<event flip="{boolean($i mod 2)}">
<xsl:apply-templates/>
</event>
</xsl:template>
</xsl:stylesheet>