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

时间:2018-02-10 11:35:55

标签: xslt xpath xslt-1.0

我需要分析以下XML输入:

:optional => true

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

<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>

我需要做的是检查两个不同PRODUCT节点中的ITEMS的BEGIN和END是否相同,如果是这种情况,请将MULTIPLE节点添加为标志。 有关如何进行的任何想法? 这就是我认为它可以工作的方式:

&#13;
&#13;
<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>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

这可以通过查找ITEM元素

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

然后,您只需要一个匹配ITEM元素的模板,其中密钥中至少有2个项目

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

将此与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]]">

答案 1 :(得分:1)

您可以通过匹配ITEM上下文来尝试这种方式:

<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>