在XSLT中与可选节点匹配和合并

时间:2016-08-17 10:18:09

标签: xml xslt xslt-1.0

我有一个包含多个父节点的示例XML消息。要求是两个父节点相同,合并子节点。这在所有节点都存在时工作正常,但在可选节点不存在时不起作用

示例消息:1存在可选节点

<document>
<body>
    <party>
        <gtin>1000909090</gtin>
        <pos>
            <attrGroupMany name="temperatureInformation">
                <row>
                    <gtin>1000909090</gtin>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">   <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE1</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE2</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">    <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE3</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE4</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>                    
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">    <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE5</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE6</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrGroupMany name="temperatureStats">      <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE7</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE8</attr>
                        </row>
                    </attrGroupMany>
                </row>
            </attrGroupMany>
        </pos>
    </party>    
</body>
</document>

以下示例XSLT可以正常删除'attrGroupMany name =“temperatureInformation”'中的副本

使用XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">



<xsl:key name="group" match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row"
    use="concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature'])"/>

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="attrGroupMany[@name = 'temperatureInformation']">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="row[generate-id() = generate-id(key('group', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))[1])]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="attrGroupMany[@name = 'temperatureStats']">
    <xsl:copy>
        <xsl:apply-templates select="@* | key('group', concat(generate-id(ancestor::pos), '|',../attr[@name = 'temperatureCode'], '|', ../attrQualMany[@name = 'temperature']))/attrGroupMany[@name = 'temperatureStats']/row"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

与上述XSLT无关的示例消息2是

<document>
<body>
    <party>
        <gtin>1000909090</gtin>
        <pos>
            <attrGroupMany name="temperatureInformation">
                <row>
                    <gtin>1000909090</gtin>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                </row>
                <row>
                    <attr name="temperatureCode">STORAGE</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>
                        <value qual="CC">20</value>
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">    <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE3</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE4</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrQualMany name="temperature">
                        <value qual="FAH">10</value>                    
                    </attrQualMany>
                    <attrGroupMany name="temperatureStats">    <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE5</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE6</attr>
                        </row>
                    </attrGroupMany>
                </row>
                <row>
                    <attr name="temperatureCode">HANDLING</attr>
                    <attrGroupMany name="temperatureStats">      <!--  optional group -->
                        <row>
                            <attr name="StatsCode">CODE7</attr>
                        </row>
                        <row>
                            <attr name="StatsCode">CODE8</attr>
                        </row>
                    </attrGroupMany>
                </row>
            </attrGroupMany>
        </pos>
    </party>    
</body>
</document>

有人可以让我知道如何处理匹配n合并中的可选节点

示例消息2的预期输出是

<?xml version="1.0" encoding="UTF-8"?>
<document>
<body>
  <party>
     <gtin>1000909090</gtin>
     <pos>
        <attrGroupMany name="temperatureInformation">
           <row>
              <gtin>1000909090</gtin>
              <attr name="temperatureCode">STORAGE</attr>
              <attrQualMany name="temperature">
                 <value qual="FAH">10</value>
                 <value qual="CC">20</value>
              </attrQualMany>
              <attrGroupMany name="temperatureStats">                   
                 <row>
                    <attr name="StatsCode">CODE3</attr>
                 </row>
                 <row>
                    <attr name="StatsCode">CODE4</attr>
                 </row>
              </attrGroupMany>
           </row>
           <row>
              <attr name="temperatureCode">HANDLING</attr>
              <attrQualMany name="temperature">
                 <value qual="FAH">10</value>
              </attrQualMany>
              <attrGroupMany name="temperatureStats">
                 <row>
                    <attr name="StatsCode">CODE5</attr>
                 </row>
                 <row>
                    <attr name="StatsCode">CODE6</attr>
                 </row>
              </attrGroupMany>
           </row>
           <row>
              <attr name="temperatureCode">HANDLING</attr>
              <attrGroupMany name="temperatureStats">
                 <row>
                    <attr name="StatsCode">CODE7</attr>
                 </row>
                 <row>
                    <attr name="StatsCode">CODE8</attr>
                 </row>
              </attrGroupMany>
           </row>
        </attrGroupMany>
     </pos>
  </party>
</body>
</document>

有人可以让我知道如何处理匹配n合并中的可选节点。谢谢

2 个答案:

答案 0 :(得分:1)

你还没有解释你想要做的事情背后的逻辑,但是通过从这个问题和之前的问题看XSLT,你正在对attrGroupMany[@name = 'temperatureInformation']/row元素进行分组,但是它是一个串联的元素。祖先pos和&#34; temperatureCode&#34;和&#34;温度&#34;。

然后,对于每个此类不同的row,您似乎想要添加所有<attrGroupMany name="temperatureStats">元素。如果你说它是可选的,那么拥有一个匹配这个元素的模板将不起作用。相反,请使用与父row匹配的模板,并使用该模板从键中的所有元素中选择所有子元素。

<xsl:template match="attrGroupMany[@name = 'temperatureInformation']/row">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[not(self::attrGroupMany[@name = 'temperatureStats'])]"/> 
        <attrGroupMany name="temperatureStats">
            <xsl:apply-templates select="key('group', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))/attrGroupMany[@name = 'temperatureStats']/row"/>
        </attrGroupMany>
    </xsl:copy>
</xsl:template>

我假设所有StatsCode在这里都是不同的。如果可能存在重复,并且您想删除此类重复项,则需要在您的问题中说明。

试试这个XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="xml" indent="yes" />

<xsl:key name="group" match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row"
    use="concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature'])"/>

<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="attrGroupMany[@name = 'temperatureInformation']">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="row[generate-id() = generate-id(key('group', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))[1])]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="attrGroupMany[@name = 'temperatureInformation']/row">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[not(self::attrGroupMany[@name = 'temperatureStats'])]"/> 
        <attrGroupMany name="temperatureStats">
            <xsl:apply-templates select="key('group', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))/attrGroupMany[@name = 'temperatureStats']/row"/>
        </attrGroupMany>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

答案 1 :(得分:0)

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"    version="1.0">

<xsl:output method="xml" indent="yes" />

<xsl:key name="grouptemperatureInformation" match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row"
use="concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature'])"/>

<xsl:key name="grouptemperatureStats" 
         match="party/pos/attrGroupMany[@name = 'temperatureInformation']/row/attrGroupMany[@name = 'temperatureStats']/row"
         use="concat(generate-id(ancestor::pos), '|', ../../../attr[@name = 'temperatureCode'], '|', ../../../attrQualMany[@name = 'temperature'], '|', attr[@name = 'StatsCode'])"/>


<xsl:template match="@* | node()">
    <xsl:copy>
        <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="attrGroupMany[@name = 'temperatureInformation']">
    <xsl:copy>
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="row[generate-id() = generate-id(key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))[1])]"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="attrGroupMany[@name = 'temperatureInformation']/row">
    <xsl:variable name="group" select="key('grouptemperatureInformation', concat(generate-id(ancestor::pos), '|', attr[@name = 'temperatureCode'], '|', attrQualMany[@name = 'temperature']))/attrGroupMany[@name='temperatureStats']/row" />
    <xsl:copy>
        <xsl:apply-templates select="@*|node()[not(self::attrGroupMany[@name = 'temperatureStats'])]"/> 
        <attrGroupMany name="temperatureStats">             
            <xsl:apply-templates select="@* | $group[generate-id() = generate-id(key('grouptemperatureStats', concat(generate-id(ancestor::pos), '|', ../../../attr[@name = 'temperatureCode'], '|', ../../../attrQualMany[@name = 'temperature'], '|', attr[@name = 'StatsCode']))[1])]"/> 
        </attrGroupMany>
    </xsl:copy>
 </xsl:template>
 </xsl:stylesheet>