分组时如何去除空?

How to remove empty when grouping?

利用来自 的知识,我提出了以下 XSLT:

<?xml version='1.0' encoding='utf-8'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
    xmlns:json='http://james.newtonking.com/projects/json'
    version="3.0">
    <xsl:output omit-xml-declaration='yes' method='xml' version='1.0' />
    <xsl:template match='/'>
        <edi856>
            <xsl:for-each-group select="/ns0:X12_00401_856/ns0:HLLoop1" group-starting-with="/ns0:X12_00401_856/ns0:HLLoop1[ns0:HL03='Q']">
                <hlq json:Array='true'>
                    <hlqId>
                        <xsl:value-of select="current-group()/ns0:TSD/TSD01"/>
                    </hlqId>
                    <xsl:variable name="hlq" select="current-group()" />
                    <xsl:variable name="hlq-id" select="$hlq/ns0:TSD/TSD01" />
                    <xsl:for-each-group select="current-group()[position() gt 1]" group-starting-with="/ns0:X12_00401_856/ns0:HLLoop1[ns0:HL/HL03='I']">
                        <hli json:Array='true'>
                            <hlqId>
                                <xsl:value-of select="$hlq-id"/>
                            </hlqId>
                            <hliId>
                                <xsl:value-of select="current-group()/ns0:LIN/LIN03"/>
                            </hliId>
                        </hli>
                    </xsl:for-each-group>
                </hlq>
            </xsl:for-each-group>
        </edi856>
    </xsl:template>
</xsl:stylesheet>

当我将它与以下输入 (Input#1) 一起使用时:

<ns0:X12_00401_856 xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
    <ns0:HLLoop1>
        <ns0:HL>
            <HL03>Q</HL03>
        </ns0:HL>
        <ns0:TSD>
            <TSD01>DELIVERY1</TSD01>
        </ns0:TSD>
    </ns0:HLLoop1>
    <ns0:HLLoop1>
        <ns0:HL>
            <HL03>I</HL03>
        </ns0:HL>
        <ns0:LIN>
            <LIN03>asnLineItem1</LIN03>
        </ns0:LIN>
    </ns0:HLLoop1>
</ns0:X12_00401_856>

输出生成为(实际#1):

<edi856 xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
    xmlns:json="http://james.newtonking.com/projects/json">
    <hlq json:Array="true">
        <hlqId>DELIVERY1</hlqId>
        <hli json:Array="true">
            <hlqId>DELIVERY1</hlqId>
            <hliId/>
        </hli>
        <hli json:Array="true">
            <hlqId>DELIVERY1</hlqId>
            <hliId>asnLineItem1</hliId>
        </hli>
    </hlq>
</edi856>

我希望输出只有 1 hli (Expected#1):

<edi856 xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
    xmlns:json="http://james.newtonking.com/projects/json">
    <hlq json:Array="true">
        <hlqId>DELIVERY1</hlqId>
        <hli json:Array="true">
            <hlqId>DELIVERY1</hlqId>
            <hliId>asnLineItem1</hliId>
        </hli>
    </hlq>
</edi856>

当我删除 HL03=I 的 HLLLoop1 时,我希望 hli 不存在于输出中,但它仍然存在。

输入#2:

<ns0:X12_00401_856 xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006">
    <ns0:HLLoop1>
        <ns0:HL>
            <HL03>Q</HL03>
        </ns0:HL>
        <ns0:TSD>
            <TSD01>DELIVERY1</TSD01>
        </ns0:TSD>
    </ns0:HLLoop1>
</ns0:X12_00401_856>

实际#2:

<edi856 xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
    xmlns:json="http://james.newtonking.com/projects/json">
    <hlq json:Array="true">
        <hlqId>DELIVERY1</hlqId>
        <hli json:Array="true">
            <hlqId>DELIVERY1</hlqId>
            <hliId/>
        </hli>
    </hlq>
</edi856>

预计#2:

<edi856 xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:ns0="http://schemas.microsoft.com/BizTalk/EDI/X12/2006"
    xmlns:json="http://james.newtonking.com/projects/json">
    <hlq json:Array="true">
        <hlqId>DELIVERY1</hlqId>
    </hlq>
</edi856>

我在这里缺少什么来满足我的期望?

也许将内部 for-each-group 的内容包装到 <xsl:if test="self::ns0:HLLoop1[ns0:HL/HL03='I']">...</xsl:if> 中会有所帮助,但我不确定我是否理解了输入数据的结构和所需的分组要求。

而且我认为对于外部 for-each-group 你宁愿 group-starting-with="ns0:HLLoop1[ns0:HL/HL03='Q']" 但你也需要将 for-each-group 的主体包装成 <xsl:if test="self::ns0:HLLoop1[ns0:HL/HL03='Q']">..</xsl:if> 以输出结果仅适用于匹配组,而不适用于 for-each-group 为您提供的不匹配项。

所以模板应该是

<xsl:template match='/'>
    <edi856>
        <xsl:variable name="bsn02" select="/ns0:X12_00401_856/ns0:BSN/BSN02" />
        <xsl:for-each-group select="/ns0:X12_00401_856/ns0:HLLoop1" group-starting-with="ns0:HLLoop1[ns0:HL/HL03='Q']">
            <xsl:if test="self::ns0:HLLoop1[ns0:HL/HL03='Q']">
                <hlq json:Array='true'>
                    <hlqId>
                        <xsl:value-of select="current-group()/ns0:TSD/TSD01"/>
                    </hlqId>
                    <bsn02>
                        <xsl:value-of select="$bsn02"/>
                    </bsn02>
                    <xsl:variable name="hlq" select="current-group()" />
                    <xsl:variable name="hlq-id" select="$hlq/ns0:TSD/TSD01" />
                    <xsl:for-each-group select="current-group()[position() gt 1]" group-starting-with="ns0:HLLoop1[ns0:HL/HL03='I']">
                        <xsl:if test="self::ns0:HLLoop1[ns0:HL/HL03='I']">
                            <hli json:Array='true'>
                                <hlqId>
                                    <xsl:value-of select="$hlq-id"/>
                                </hlqId>
                                <bsn02>
                                    <xsl:value-of select="$bsn02"/>
                                </bsn02>
                                <hliId>
                                    <xsl:value-of select="current-group()/ns0:LIN/LIN03"/>
                                </hliId>
                            </hli>                            
                        </xsl:if>
                    </xsl:for-each-group>
                </hlq>                    
            </xsl:if>
        </xsl:for-each-group>
    </edi856>
</xsl:template>

这些样本与前一个样本之间的区别在于,您的分组总体始终以匹配项目 (https://www.w3.org/TR/xslt-30/#xsl-for-each-group) 开始:

If the group-starting-with attribute is present, then its value must be a pattern.

The items in the population are examined in population order. If an item matches the pattern, or is the first item in the population, then a new group is created and the item becomes its first member. Otherwise, the item is appended to the same group as its preceding item within the population.