使用xslt查找具有相同属性的节点并添加新节点

使用xslt查找具有相同属性的节点并添加新节点,xslt,xpath,xslt-1.0,Xslt,Xpath,Xslt 1.0,我需要分析以下XML输入: <LIST> <PRODUCT TYPE="1" REP="0"> <SUB CAT="1.1" COUNT="2"> <ITEM NAME="OCC" BEGIN="0" ND="49"> </ITEM> <ITEM NAME="OCC" BEGIN="0" END="49">

我需要分析以下XML输入:

<LIST>

    <PRODUCT TYPE="1" REP="0">
        <SUB CAT="1.1" COUNT="2">


            <ITEM  NAME="OCC" BEGIN="0" ND="49">

            </ITEM>


            <ITEM NAME="OCC"  BEGIN="0" END="49">

            </ITEM>

        </SUB>
    </PRODUCT>

    <PRODUCT TYPE="1" REP="1">
        <SUB CAT="1.1" COUNT="1">

            <ITEM  NAME="PRC" BEGIN="0" END="49">

            </ITEM>
        </SUB>
    </PRODUCT>

</LIST>

并使用Xslt对其进行转换,以获得以下结果:

<LIST>

    <PRODUCT TYPE="1" REP="0">
        <SUB CAT="1.1" COUNT="2">

            <MULTIPLE />
            <ITEM  NAME="OCC" BEGIN="0" END="49">

            </ITEM>

            <MULTIPLE />
            <ITEM NAME="OCC"  BEGIN="0" END="49">

            </ITEM>

        </SUB>
    </PRODUCT>

    <PRODUCT TYPE="1" REP="1">
        <SUB CAT="1.1" COUNT="1">
            <MULTIPLE />
            <ITEM  NAME="PRC" BEGIN="0" END="49">

            </ITEM>
        </SUB>
    </PRODUCT>

</LIST>

我需要做的是检查两个不同产品节点中项目的开始和结束是否相同,如果是这种情况,则添加多个节点作为标志。 你知道怎么做吗? 这就是我认为它可以工作的方式:


这可以通过一个键来查找
元素来实现

<xsl:key name="item" match="ITEM" use="concat(@BEGIN, '|', @END)" />
将其与XSLT标识转换结合使用,可以得到以下XSLT

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

  <xsl:key name="item" match="ITEM" use="concat(@BEGIN, '|', @END)" />

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

  <xsl:template match="ITEM[key('item', concat(@BEGIN, '|', @END))[2]]">
    <MULTIPLE />
    <xsl:call-template name="identity" />
  </xsl:template>
</xsl:stylesheet>

如果您希望将其限制为在同一产品和子类别中查找匹配项,请更改此项的键

<xsl:key name="item" match="ITEM" use="concat(../../@TYPE, '|', ../@CAT, '|', @BEGIN, '|', @END)" />

并相应地调整模板匹配

<xsl:template match="ITEM[key('item', concat(../../@TYPE, '|', ../@CAT, '|', @BEGIN, '|', @END))[2]]">

这可以通过一个键来查找
元素来实现

<xsl:key name="item" match="ITEM" use="concat(@BEGIN, '|', @END)" />
将其与XSLT标识转换结合使用,可以得到以下XSLT

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

  <xsl:key name="item" match="ITEM" use="concat(@BEGIN, '|', @END)" />

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

  <xsl:template match="ITEM[key('item', concat(@BEGIN, '|', @END))[2]]">
    <MULTIPLE />
    <xsl:call-template name="identity" />
  </xsl:template>
</xsl:stylesheet>

如果您希望将其限制为在同一产品和子类别中查找匹配项,请更改此项的键

<xsl:key name="item" match="ITEM" use="concat(../../@TYPE, '|', ../@CAT, '|', @BEGIN, '|', @END)" />

并相应地调整模板匹配

<xsl:template match="ITEM[key('item', concat(../../@TYPE, '|', ../@CAT, '|', @BEGIN, '|', @END))[2]]">

通过匹配项目上下文,您可以这样尝试:

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

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

    <xsl:template match="ITEM">
        <xsl:if test="(
            (@BEGIN = ancestor::PRODUCT/following-sibling::PRODUCT/descendant::ITEM/@BEGIN) and 
            (@END = ancestor::PRODUCT/following-sibling::PRODUCT/descendant::ITEM/@END))
             or (
            (@BEGIN = ancestor::PRODUCT/preceding-sibling::PRODUCT/descendant::ITEM/@BEGIN) and 
            (@END = ancestor::PRODUCT/preceding-sibling::PRODUCT/descendant::ITEM/@END)
            )
            ">
        <xsl:element name="MULTIPLE"/>
        </xsl:if>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

通过匹配项目上下文,您可以这样尝试:

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

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

    <xsl:template match="ITEM">
        <xsl:if test="(
            (@BEGIN = ancestor::PRODUCT/following-sibling::PRODUCT/descendant::ITEM/@BEGIN) and 
            (@END = ancestor::PRODUCT/following-sibling::PRODUCT/descendant::ITEM/@END))
             or (
            (@BEGIN = ancestor::PRODUCT/preceding-sibling::PRODUCT/descendant::ITEM/@BEGIN) and 
            (@END = ancestor::PRODUCT/preceding-sibling::PRODUCT/descendant::ITEM/@END)
            )
            ">
        <xsl:element name="MULTIPLE"/>
        </xsl:if>
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>