xslt 返回以下兄弟姐妹的选择

Posted

技术标签:

【中文标题】xslt 返回以下兄弟姐妹的选择【英文标题】:xslt return selection of following siblings 【发布时间】:2013-06-25 15:26:41 【问题描述】:

我有一个 XML 选择(已编辑)

<items>                 
    <item id="00100537" label="A/137i r" lcn="005417713" notes="A/137-160"/>
    <item id="00100538" label="A/137i v" lcn="" notes=""/>
    <item id="00100539" label="A/137ii r" lcn="" notes=""/>
    <item id="00100540" label="A/137ii v" lcn="" notes=""/>
    <item id="00100678" label="A/159iii v" lcn="" notes=""/>
    <item id="00100679" label="A/159iv r" lcn="" notes=""/>
    <item id="00100680" label="A/159iv v" lcn="" notes=""/>
    <item id="00100681" label="A/160i r" lcn="" notes=""/>
    <item id="00100682" label="A/160i v" lcn="" notes=""/>
    <item id="00100683" label="A/160ii r" lcn="" notes=""/>
    <item id="00100684" label="A/160ii v" lcn="" notes=""/>
    <item id="00100685" label="A/160iii r" lcn="" notes=""/>
    <item id="00100686" label="A/160iii v" lcn="" notes=""/>
    <item id="00100687" label="A/161i r" lcn="005417714" notes="A/161-182"/>
    <item id="00100688" label="A/161i v" lcn="" notes=""/>
    <item id="00100819" label="A/182ii v" lcn="" notes=""/>
    <item id="00100820" label="A/182iii r" lcn="" notes=""/>
    <item id="00100821" label="A/182iii v" lcn="" notes=""/>
    <item id="00100822" label="A/183i r" lcn="005417715" notes="A/183-218"/>
    <item id="00100823" label="A/183i v" lcn="" notes=""/>
    <item id="00100975" label="A/216iii r" lcn="" notes=""/>
    <item id="00100976" label="A/216iii v" lcn="" notes=""/>
    <item id="00100977" label="A/217i r" lcn="" notes=""/>
    <item id="00100978" label="A/217i v" lcn="" notes=""/>
    <item id="00100979" label="A/217ii r" lcn="" notes=""/>
    <item id="00100980" label="A/217ii v" lcn="" notes=""/>
    <item id="00100981" label="A/218i r" lcn="" notes=""/>
    <item id="00100982" label="A/218i v" lcn="" notes=""/>
    <item id="00100983" label="A/218ii r" lcn="" notes=""/>
    <item id="00100984" label="A/218ii v" lcn="" notes=""/>
    <item id="00100985" label="A/219i r" lcn="005417716" notes="A/219-248"/>
    <item id="00100986" label="A/219 v" lcn="" notes=""/>
    <item id="00100987" label="A/219ii r" lcn="" notes=""/>
    <item id="00101061" label="A/248 r" lcn="" notes=""/>
    <item id="00101062" label="A/248 v" lcn="" notes=""/>
</items>

我希望能够在下一个 lcn 之前从给定 lcn 获取所有后续节点。

如果我从 lcn='005417714' 开始,我知道有 4 个以下节点。

但是当我尝试做这样的事情时

<xsl:for-each select="/items/item[@lcn='005417714']/following-sibling::*">

我得到了所有以下兄弟姐妹。如何在下一个非空 lcn 属性之前获取所有后续兄弟姐妹?所以只检索以下 4 个兄弟姐妹?谢谢

【问题讨论】:

XSLT 1.0,但我没有尝试过 2.0。我可以从 2.0 开始给出一个解决方案,看看是否可行。 【参考方案1】:

使用 xslt-1.0,您可以尝试以下基于密钥的解决方案: (只是为了展示它是如何工作的)

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:key name="kfItem" match="item[@lcn = '']"
         use="generate-id(preceding-sibling::item[@lcn != ''][1])"/>

    <xsl:template match="/*">
        <items>
            <xsl:apply-templates select="item[@lcn != '']"/>
        </items>
    </xsl:template>

    <xsl:template match="item">
        <lcn lcn="@lcn">
            <xsl:copy-of select="."/>
            <xsl:copy-of select="key('kfItem', generate-id())"/>
        </lcn>
    </xsl:template>
</xsl:stylesheet>

这将生成以下输出:

<items>
  <lcn lcn="005417713">
    <item id="00100537" label="A/137i r" lcn="005417713" notes="A/137-160"/>
    <item id="00100538" label="A/137i v" lcn="" notes=""/>
    <item id="00100539" label="A/137ii r" lcn="" notes=""/>
    <item id="00100540" label="A/137ii v" lcn="" notes=""/>
    <item id="00100678" label="A/159iii v" lcn="" notes=""/>
    <item id="00100679" label="A/159iv r" lcn="" notes=""/>
    <item id="00100680" label="A/159iv v" lcn="" notes=""/>
    <item id="00100681" label="A/160i r" lcn="" notes=""/>
    <item id="00100682" label="A/160i v" lcn="" notes=""/>
    <item id="00100683" label="A/160ii r" lcn="" notes=""/>
    <item id="00100684" label="A/160ii v" lcn="" notes=""/>
    <item id="00100685" label="A/160iii r" lcn="" notes=""/>
    <item id="00100686" label="A/160iii v" lcn="" notes=""/>
  </lcn>
  <lcn lcn="005417714">
    <item id="00100687" label="A/161i r" lcn="005417714" notes="A/161-182"/>
    <item id="00100688" label="A/161i v" lcn="" notes=""/>
    <item id="00100819" label="A/182ii v" lcn="" notes=""/>
    <item id="00100820" label="A/182iii r" lcn="" notes=""/>
    <item id="00100821" label="A/182iii v" lcn="" notes=""/>
  </lcn>
  <lcn lcn="005417715">
    <item id="00100822" label="A/183i r" lcn="005417715" notes="A/183-218"/>
    <item id="00100823" label="A/183i v" lcn="" notes=""/>
    <item id="00100975" label="A/216iii r" lcn="" notes=""/>
    <item id="00100976" label="A/216iii v" lcn="" notes=""/>
    <item id="00100977" label="A/217i r" lcn="" notes=""/>
    <item id="00100978" label="A/217i v" lcn="" notes=""/>
    <item id="00100979" label="A/217ii r" lcn="" notes=""/>
    <item id="00100980" label="A/217ii v" lcn="" notes=""/>
    <item id="00100981" label="A/218i r" lcn="" notes=""/>
    <item id="00100982" label="A/218i v" lcn="" notes=""/>
    <item id="00100983" label="A/218ii r" lcn="" notes=""/>
    <item id="00100984" label="A/218ii v" lcn="" notes=""/>
  </lcn>
  <lcn lcn="005417716">
    <item id="00100985" label="A/219i r" lcn="005417716" notes="A/219-248"/>
    <item id="00100986" label="A/219 v" lcn="" notes=""/>
    <item id="00100987" label="A/219ii r" lcn="" notes=""/>
    <item id="00101061" label="A/248 r" lcn="" notes=""/>
    <item id="00101062" label="A/248 v" lcn="" notes=""/>
  </lcn>
</items>

【讨论】:

像这样是要走的路。您可以完全在 xpath 中完成,但 key 的性能要好得多。我有一个 4 MB(不是一个巨大的文件)与使用 xpath 的兄弟模板匹配——而且速度很慢。我换了一把这样的钥匙,现在一眨眼就跑了。【参考方案2】:

在 XSLT 2.0 中,您可以使用&lt;xsl:for-each-group&gt;,尤其是它的group-starting-with 属性来遍历以非空lcn 开头的元素组。在 XSLT 1.0 中有多种可能性。最简单的方法是

<xsl:for-each select="/items/item[@lcn='005417714']">
  <xsl:for-each select="following-sibling::*[
         generate-id(preceding-sibling::item[@lcn != ''][1])
       = generate-id(current())]">
  </xsl:for-each>
</xsl:for-each>

它检查我们目标项目的所有以下同级,并选择那些最近的具有非空lcn 属性的前同级是目标项目。

如果您想迭代所有“部分”而不是只针对一个特定的部分,那么基于键的分组方法suggested by hr_117 会更有效。

【讨论】:

以上是关于xslt 返回以下兄弟姐妹的选择的主要内容,如果未能解决你的问题,请参考以下文章

如果有兄弟姐妹,则 jquery 兄弟姐妹()似乎包括选择器,但如果没有,则不包括

jQuery选择除self之外的所有兄弟姐妹和孩子

如果值匹配,XSLT 会更改兄弟元素的子元素值

(CSS / jQuery/ XPath) 用于从姐妹/兄弟节点 (DOM) 获取内部文本的选择器

选择除兄弟姐妹和自我之外的所有元素

徘徊在兄弟姐妹身上只会影响兄弟姐妹