【问题标题】:Use XSLT key() function to lookup nodes based on two attributes in separate elements使用 XSLT key() 函数根据不同元素中的两个属性查找节点
【发布时间】:2013-02-14 02:03:24
【问题描述】:

我正在尝试使用 XSLT key() 函数返回 XML 文件中符合以下两个条件的所有 <Code> 元素:

Code[code=$code] AND ancestor::CodeType[type=$codeType]`


以下是输入 XML 的简化示例:

<Items>
    <Item code-number="C1" category="ABC" />
    <Item code-number="C3" category="ABC" />
    <Item code-number="C1" category="XYZ" />
</Items>

<CodeTypes>
    <CodeType type="ABC">
        <SubType title="Category III Codes">   <!-- <SubType> elements are optional -->
            <SubType title="Subcategory III-15 Codes">
                <Code code="C1" description="Red" />
                <Code code="C2" description="Green" />
                <Code code="C3" description="Blue" />
                <Code code="C3" description="Purple" />   <!-- Same code can appear more than once -->
            </SubType>
        </SubType>
    <CodeType>
    <CodeType type="XYZ">
        <Code code="C1" description="Black" />   <!-- Same code can be used for multiple CodeTypes -->
        <Code code="C2" description="Orange" />
        <Code code="C3" description="Yellow" />
    <CodeType>
</CodeTypes>

请注意,cmets 实际上并不存在于实际的 XML 中,我只是在此处添加它们以阐明 XML 结构。


这是我尝试使用的 XSLT 转换,虽然它似乎不起作用:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="LookupMatchingCodeElements" match="Code" use="concat(../@code, '+', ancestor::CodeType/@type)" />

    <xsl:template match="Item">
        <xsl:call-template name="GetCodeElements">
            <xsl:with-param name="code" select="@code-number" />
            <xsl:with-param name="codeType" select="@category" />
        </xsl:call-template>
    </xsl:template>

    <xsl:template name="GetCodeElements">
        <xsl:param name="code" />
        <xsl:param name="codeType" />

        <xsl:for-each select="key('LookupMatchingCodeElements', concat($code, '+', $codeType))">
            <!-- process each <Code> element -->
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>


这就是我希望 key() 函数返回不同输入的内容:

<!-- For code="C1" AND codeType="ABC" -->
<Code code="C1" description="Red" />

<!-- For code="C3" AND codeType="ABC" -->
<Code code="C3" description="Blue" />
<Code code="C3" description="Purple" />

<!-- For code="C1" AND codeType="XYZ" -->
<Code code="C1" description="Black" />


这可以通过 key() 函数实现吗?由于&lt;Item&gt; 和&lt;Code&gt; 元素都有数十万个,因此能够使用&lt;xsl:key&gt; 非常重要。

【问题讨论】:

    标签: xslt xslkey


    【解决方案1】:

    使用:

     <xsl:key name="kCode" match="Code"
      use="concat(ancestor::CodeType[1]/@type, '+', @code)"/>
    

    这是一个完整的转换:

    <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="kCode" match="Code"
      use="concat(ancestor::CodeType[1]/@type, '+', @code)"/>
    
     <xsl:template match="/">
      <xsl:copy-of select="key('kCode', 'ABC+C1')"/>
    ====================
      <xsl:copy-of select="key('kCode', 'ABC+C3')"/>
    ====================
      <xsl:copy-of select="key('kCode', 'XYZ+C1')"/>
     </xsl:template>
    </xsl:stylesheet>
    

    当此转换应用于以下文档时(提供的 XML 文本 -- 已纠正格式错误):

    <t>
        <Items>
            <Item code-number="C1" category="ABC" />
            <Item code-number="C3" category="ABC" />
            <Item code-number="C1" category="XYZ" />
        </Items>
        <CodeTypes>
            <CodeType type="ABC">
                <SubType title="Category III Codes">
                    <!-- <SubType> elements are optional -->
                    <SubType title="Subcategory III-15 Codes">
                        <Code code="C1" description="Red" />
                        <Code code="C2" description="Green" />
                        <Code code="C3" description="Blue" />
                        <Code code="C3" description="Purple" />
                        <!-- Same code can appear more than once -->
                    </SubType>
                </SubType>
            </CodeType>
            <CodeType type="XYZ">
                <Code code="C1" description="Black" />
                <!-- Same code can be used for multiple CodeTypes -->
                <Code code="C2" description="Orange" />
                <Code code="C3" description="Yellow" />
            </CodeType>
        </CodeTypes>
    </t>
    

    产生想要的正确结果:

    <Code code="C1" description="Red"/>
    ====================
      <Code code="C3" description="Blue"/>
    <Code code="C3" description="Purple"/>
    ====================
      <Code code="C1" description="Black"/>
    

    【讨论】:

    • 哇! XSLT 继续让我惊讶于它的强大。这实际上将一个需要 5 个多小时的过程缩短到几秒钟。谢谢迪米特!
    • @MTS,不客气。是的,XSLT 既强大又优雅——更不用说 XSLT 2.0 和现在即将推出的 XSLT 3.0。
    猜你喜欢
    • 1970-01-01
    • 2016-04-12
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-11
    • 2018-08-25
    相关资源
    最近更新 更多