XSLT 1.0 - 如何将 2 个元素/兄弟元素组合成 1 个组

Posted

技术标签:

【中文标题】XSLT 1.0 - 如何将 2 个元素/兄弟元素组合成 1 个组【英文标题】:XSLT 1.0 - How to combine 2 elements/siblings into 1 group 【发布时间】:2021-09-19 20:09:13 【问题描述】:

我希望我没有严重破坏标题。

我是 XML 和 XSLT 转换的初学者,经过几天的研究和一些严重的试验和错误,我走到了这一步,但现在我绝望了。我似乎无法找到组合 customer_ids 的方法,因为它们可以来自 2 个不同的元素,并且结果必须具有唯一的 customer_ids。

我应该如何继续这个?

这里是源 XML 的示例,我需要转换。

<result>
<row>
    <string>HR-039780</string>
    <string>PER-013</string>
    <null/>
    <string>HelpRequest</string>
    <string>CID-009</string>
    <string>SP-004</string>
    <string>SG-002</string>
</row>
<row>
    <string>SR-003470</string>
    <null/>
    <string>PER-013</string>
    <string>ServiceRequest</string>
    <string>CID-009</string>
    <string>SP-004</string>
    <string>SG-002</string>
</row>
<row>
    <string>SR-009626</string>
    <null/>
    <string>PER-017</string>
    <string>ServiceRequest</string>
    <string>CID-001</string>
    <string>SP-002</string>
    <string>SG-001</string>
</row>
<row>
    <string>HR-035112</string>
    <string>PER-029</string>
    <null/>
    <string>HelpRequest</string>
    <string>CID-015</string>
    <string>SP-002</string>
    <string>SG-001</string>
</row>
<row>
    <string>HR-028904</string>
    <string>PER-024</string>
    <null/>
    <string>HelpRequest</string>
    <string>CID-009</string>
    <string>SP-004</string>
    <string>SG-002</string>
</row>
</result>

这是我正在使用的 XSLT。 通过使用键,我得到了其他唯一值。

<xsl:transform 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:key name="support_id" match="*" use="child::*[6]"/>
    <xsl:key name="support_grp_id" match="*" use="child::*[7]"/>
    <xsl:key name="company_id" match="*" use="child::*[5]"/>
    <!-- 
    <xsl:key name="customer_id" match="*" use="**???**"/>
    -->
    
    <xsl:template match="/">
        <data>
        <xsl:for-each select="result/row">
            <xsl:if test="child::*[4] = 'HelpRequest'">
                <work_order>
                    <work_order_id><xsl:value-of select = "child::*[1]"/></work_order_id>
                    <customer_id><xsl:value-of select = "child::*[2]"/></customer_id>
                    <work_type><xsl:value-of select = "child::*[4]"/></work_type>
                    <company_id><xsl:value-of select = "child::*[5]"/></company_id>
                    <support_id><xsl:value-of select = "child::*[6]"/></support_id>
                    <support_grp_id><xsl:value-of select = "child::*[7]"/></support_grp_id>
                </work_order>
            </xsl:if>
            <xsl:if test="child::*[4] = 'ServiceRequest'">
                <work_order>
                    <work_order_id><xsl:value-of select = "child::*[1]"/></work_order_id>
                    <customer_id><xsl:value-of select = "child::*[3]"/></customer_id>
                    <work_type><xsl:value-of select = "child::*[4]"/></work_type>
                    <company_id><xsl:value-of select = "child::*[5]"/></company_id>
                    <support_id><xsl:value-of select = "child::*[6]"/></support_id>
                    <support_grp_id><xsl:value-of select = "child::*[7]"/></support_grp_id>
                </work_order>
            </xsl:if>
        </xsl:for-each>
        <xsl:for-each select="//*[generate-id() = generate-id(key('support_id',child::*[6])[1])]">
            <support>
                <support_id><xsl:value-of select = "child::*[6]"/></support_id>
            </support>
        </xsl:for-each>
        <xsl:for-each select="//*[generate-id() = generate-id(key('support_grp_id',child::*[7])[1])]">
            <support_grp>
                <support_grp_id><xsl:value-of select = "child::*[7]"/></support_grp_id>
            </support_grp>
        </xsl:for-each>
        <xsl:for-each select="//*[generate-id() = generate-id(key('company_id',child::*[5])[1])]">
            <company>
                <company_id><xsl:value-of select = "child::*[5]"/></company_id>
            </company>
        </xsl:for-each>
        <!-- Problem...
        <xsl:for-each select="//*[generate-id() = generate-id(key('customer_id', **???**)[1])]">
            <customer>
                <customer_id><xsl:value-of select = "child::*[ **??? 2 OR 3 ???** ]"/></customer_id>
            </customer>
        </xsl:for-each>
        -->
        </data>
    </xsl:template>
    
</xsl:transform>

结果需要是:

<data>
    <work_order>
        <work_order_id>HR-039780</work_order_id>
        <customer_id>PER-013</customer_id>
        <work_type>HelpRequest</work_type>
        <company_id>CID-009</company_id>
        <support_id>SP-004</support_id>
        <support_grp_id>SG-002</support_grp_id>
    </work_order>
    <work_order>
        <work_order_id>SR-003470</work_order_id>
        <customer_id>PER-013</customer_id>
        <work_type>ServiceRequest</work_type>
        <company_id>CID-009</company_id>
        <support_id>SP-004</support_id>
        <support_grp_id>SG-002</support_grp_id>
    </work_order>
    <work_order>
        <work_order_id>SR-009626</work_order_id>
        <customer_id>PER-017</customer_id>
        <work_type>ServiceRequest</work_type>
        <company_id>CID-001</company_id>
        <support_id>SP-002</support_id>
        <support_grp_id>SG-001</support_grp_id>
    </work_order>
    <work_order>
        <work_order_id>HR-035112</work_order_id>
        <customer_id>PER-029</customer_id>
        <work_type>HelpRequest</work_type>
        <company_id>CID-015</company_id>
        <support_id>SP-002</support_id>
        <support_grp_id>SG-001</support_grp_id>
    </work_order>
    <work_order>
        <work_order_id>HR-028904</work_order_id>
        <customer_id>PER-024</customer_id>
        <work_type>HelpRequest</work_type>
        <company_id>CID-009</company_id>
        <support_id>SP-004</support_id>
        <support_grp_id>SG-002</support_grp_id>
    </work_order>
    <support>
        <support_id>SP-002</support_id>
    </support>
    <support>
        <support_id>SP-004</support_id>
    </support>
    <support_grp>
        <support_grp_id>SG-002</support_grp_id>
    </support_grp>
    <support_grp>
        <support_grp_id>SG-001</support_grp_id>
    </support_grp>
    <company>
        <company_id>CID-001</company_id>
    </company>
    <company>
        <company_id>CID-015</company_id>
    </company>
    <company>
        <company_id>CID-009</company_id>
    </company>
    <customer>
        <customer_id>PER-013</customer_id>
    </customer>
    <customer>
        <customer_id>PER-024</customer_id>
    </customer>
    <customer>
        <customer_id>PER-017</customer_id>
    </customer>
    <customer>
        <customer_id>PER-029</customer_id>
    </customer>
</data>

【问题讨论】:

【参考方案1】:

use="string[2]"&lt;xsl:value-of select = "string[2]"/&gt; 应该可以工作,如果我没有误解你的输入的话。对于所有的键,似乎使用match="row" 而不是match="*" 就足够了,而且效率更高。

【讨论】:

对不起,差点忘了回答。这工作得很好,谢谢! :)

以上是关于XSLT 1.0 - 如何将 2 个元素/兄弟元素组合成 1 个组的主要内容,如果未能解决你的问题,请参考以下文章

使用父元素在 XSLT 中拆分/分组

xslt将具有相同属性的相邻兄弟合并为一个,同时连接它们的文本

XSLT 如何将常用标签包装在不同的包装元素中?

如何使用 XSLT 替换命名空间中的元素?

如何使用 XSLT 从 XML 中删除元素标记

XSLT 1.0 添加元素增量 ID