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

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

问题描述:

我需要分析以下 XML 输入:

I need to analyse the following XML input:

<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对其进行变换,得到如下结果:

and transform it with Xslt to obtain the following result:

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

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

What I need to do is to check that the BEGIN and END of the ITEMS in two different PRODUCT node are the same, and if this is the case add the MULTIPLE node as a flag. Any idea on how to proceed? This is how I thought it could work:

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


<xsl:template match="//PRODUCT[@TYPE='1']/SUB[@CAT='1.1']/ITEM">
		
		
<xsl:if test="//PRODUCT[@TYPE='1']/SUB[@CAT='1.1']/ITEM /RULE (@BEGIN &lt;= current()/@BEGIN) and (@END &gt;= current()/@END)]">

			
		<xsl:element name="MULTIPLE">
										
		</xsl:element>	

			
		</xsl:if>

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

</xsl:stylesheet>

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

This can be achieved by means of a key to look up ITEM elements

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

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

Then, you just need a template that matches ITEM elements where there is at least 2 items in the key

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

将此与 XSLT 身份转换结合使用,为您提供此 XSLT

Using this in conjunction with the XSLT identity transform, gives you this 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>

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

If you wish to restrict it to look for matches in the same product and sub-category, change the key to this...

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

并相应地调整模板匹配....

And adjust the template match accordingly....

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