动态增加节点值

时间:2011-05-01 21:12:46

标签: xslt

我有一个输入xml,它具有以下结构,

<VEN>
<CUS>
    <MEM>
    <MEM>
    <MEM>
</CUS>
<CUS>
    <MEM>
    <MEM>
    <MEM>
</CUS>

每个节点在输入xml中多次出现。每个MEM都有一个@ CLM01属性 必须根据MEM节点的每20次出现分配值的节点。从第一个VEN / CUS开始,如果MEM有55个节点,那么前20个节点的@ CLM01值为'1',对于相同的VEN / CUS组合,接下来的20个节点将具有值'2',剩下的15个节点将将@ CLM01值设为'3'。

对于下一个CUS(假设此CUS有30个MEM节点)在相同VEN下,前20个MEM节点的@ CLM01值为'4',接下来的10个MEM将具有值为'5'的@ CLM01。这继续.....我希望我很清楚我想要实现的目标。

感谢。可能吗?使用xslt 1.0

以下是示例输入

<Data>
<VEN vendorId= "v1">
    <CUS custId = "c1">
        <MEM memId="m1" CLM01=""/>
        <MEM memId="m2" CLM01=""/>
        <MEM memId="m3" CLM01=""/>
        <MEM memId="m4" CLM01=""/>
        <MEM memId="m5" CLM01=""/>
    </CUS>
    <CUS custId = "c2">
        <MEM memId="m11" CLM01=""/>
        <MEM memId="m12" CLM01=""/>
        <MEM memId="m13" CLM01=""/>
        <MEM memId="m14" CLM01=""/>
        <MEM memId="m15" CLM01=""/>
        <MEM memId="m16" CLM01=""/>
        <MEM memId="m17" CLM01=""/>
        <MEM memId="m18" CLM01=""/>
    </CUS>
</VEN>
<VEN vendorId= "v2">
    <CUS custId = "c1">
        <MEM memId="m4" CLM01=""/>
        <MEM memId="m5" CLM01=""/>
        <MEM memId="m6" CLM01=""/>
        <MEM memId="m7" CLM01=""/>
        <MEM memId="m8" CLM01=""/>
    </CUS>
    <CUS custId = "c1">
        <MEM memId="m33" CLM01=""/>
        <MEM memId="m44" CLM01=""/>
        <MEM memId="m55" CLM01=""/>
        <MEM memId="m66" CLM01=""/>
        <MEM memId="m77" CLM01=""/>
        <MEM memId="m88" CLM01=""/>
        <MEM memId="m99" CLM01=""/>
        <MEM memId="m11" CLM01=""/>
    </CUS>
</VEN>

期望的输出(而不是每3次出现的MEM节点发生20次)

<Data>
<VEN vendorId= "v1">
    <CUS custId = "c1">
        <MEM memId="m1" CLM01="1"/>
        <MEM memId="m2" CLM01="1"/>
        <MEM memId="m3" CLM01="1"/>
        <MEM memId="m4" CLM01="2"/>
        <MEM memId="m5" CLM01="2"/>
    </CUS>
    <CUS custId = "c2">
        <MEM memId="m11" CLM01="3"/>
        <MEM memId="m12" CLM01="3"/>
        <MEM memId="m13" CLM01="3"/>
        <MEM memId="m14" CLM01="4"/>
        <MEM memId="m15" CLM01="4"/>
        <MEM memId="m16" CLM01="4"/>
        <MEM memId="m17" CLM01="5"/>
        <MEM memId="m18" CLM01="5"/>
    </CUS>
</VEN>
<VEN vendorId= "v2">
    <CUS custId = "c1">
        <MEM memId="m4" CLM01="6"/>
        <MEM memId="m5" CLM01="6"/>
        <MEM memId="m6" CLM01="6"/>
        <MEM memId="m7" CLM01="7"/>
        <MEM memId="m8" CLM01="7"/>
    </CUS>
    <CUS custId = "c1">
        <MEM memId="m33" CLM01="8"/>
        <MEM memId="m44" CLM01="8"/>
        <MEM memId="m55" CLM01="8"/>
        <MEM memId="m66" CLM01="9"/>
        <MEM memId="m77" CLM01="9"/>
        <MEM memId="m88" CLM01="9"/>
        <MEM memId="m99" CLM01="10"/>
        <MEM memId="m11" CLM01="10"/>
    </CUS>
</VEN>

2 个答案:

答案 0 :(得分:1)

此转化

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:ext="http://exslt.org/common">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:param name="pSize" select="3"/>


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

 <xsl:template match="/">
  <xsl:variable name="vrtfPass1">
   <xsl:apply-templates/>
  </xsl:variable>

  <xsl:variable name="vPass2" select=
   "ext:node-set($vrtfPass1)"/>

   <xsl:apply-templates select="$vPass2/*" mode="pass2"/>
 </xsl:template>

 <xsl:template match=
  "MEM[not(following-sibling::MEM)]">
   <xsl:call-template name="identity"/>

   <xsl:variable name="vPos" select=
   "count(preceding-sibling::MEM)+1"/>

   <xsl:variable name="pTimes"
        select="$pSize - ($vPos mod $pSize)"/>

   <xsl:call-template name="genMems">
    <xsl:with-param name="pTimes" select="$pTimes"/>
   </xsl:call-template>
 </xsl:template>

 <xsl:template name="genMems">
  <xsl:param name="pTimes"/>

  <xsl:if test="$pTimes >0">
   <MEM fake="yes"/>

   <xsl:call-template name="genMems">
    <xsl:with-param name="pTimes" select="$pTimes -1"/>
   </xsl:call-template>
  </xsl:if>
 </xsl:template>

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

 <xsl:template match="MEM/@CLM01" mode="pass2">
  <xsl:attribute name="CLM01">
   <xsl:variable name="vNum">
    <xsl:number count="MEM" level="any"/>
   </xsl:variable>

    <xsl:value-of select=
      "ceiling($vNum div $pSize)"/>
   </xsl:attribute>
  </xsl:template>

  <xsl:template match="MEM[@fake='yes']" mode="pass2"/>
</xsl:stylesheet>

应用于提供的XML文档时:

<Data>
    <VEN vendorId= "v1">
        <CUS custId = "c1">
            <MEM memId="m1" CLM01=""/>
            <MEM memId="m2" CLM01=""/>
            <MEM memId="m3" CLM01=""/>
            <MEM memId="m4" CLM01=""/>
            <MEM memId="m5" CLM01=""/>
        </CUS>
        <CUS custId = "c2">
            <MEM memId="m11" CLM01=""/>
            <MEM memId="m12" CLM01=""/>
            <MEM memId="m13" CLM01=""/>
            <MEM memId="m14" CLM01=""/>
            <MEM memId="m15" CLM01=""/>
            <MEM memId="m16" CLM01=""/>
            <MEM memId="m17" CLM01=""/>
            <MEM memId="m18" CLM01=""/>
        </CUS>
    </VEN>
    <VEN vendorId= "v2">
        <CUS custId = "c1">
            <MEM memId="m4" CLM01=""/>
            <MEM memId="m5" CLM01=""/>
            <MEM memId="m6" CLM01=""/>
            <MEM memId="m7" CLM01=""/>
            <MEM memId="m8" CLM01=""/>
        </CUS>
        <CUS custId = "c1">
            <MEM memId="m33" CLM01=""/>
            <MEM memId="m44" CLM01=""/>
            <MEM memId="m55" CLM01=""/>
            <MEM memId="m66" CLM01=""/>
            <MEM memId="m77" CLM01=""/>
            <MEM memId="m88" CLM01=""/>
            <MEM memId="m99" CLM01=""/>
            <MEM memId="m11" CLM01=""/>
        </CUS>
    </VEN>
</Data>

会产生想要的正确结果:

<Data>
   <VEN vendorId="v1">
      <CUS custId="c1">
         <MEM memId="m1" CLM01="1"/>
         <MEM memId="m2" CLM01="1"/>
         <MEM memId="m3" CLM01="1"/>
         <MEM memId="m4" CLM01="2"/>
         <MEM memId="m5" CLM01="2"/>
      </CUS>
      <CUS custId="c2">
         <MEM memId="m11" CLM01="3"/>
         <MEM memId="m12" CLM01="3"/>
         <MEM memId="m13" CLM01="3"/>
         <MEM memId="m14" CLM01="4"/>
         <MEM memId="m15" CLM01="4"/>
         <MEM memId="m16" CLM01="4"/>
         <MEM memId="m17" CLM01="5"/>
         <MEM memId="m18" CLM01="5"/>
      </CUS>
   </VEN>
   <VEN vendorId="v2">
      <CUS custId="c1">
         <MEM memId="m4" CLM01="6"/>
         <MEM memId="m5" CLM01="6"/>
         <MEM memId="m6" CLM01="6"/>
         <MEM memId="m7" CLM01="7"/>
         <MEM memId="m8" CLM01="7"/>
      </CUS>
      <CUS custId="c1">
         <MEM memId="m33" CLM01="8"/>
         <MEM memId="m44" CLM01="8"/>
         <MEM memId="m55" CLM01="8"/>
         <MEM memId="m66" CLM01="9"/>
         <MEM memId="m77" CLM01="9"/>
         <MEM memId="m88" CLM01="9"/>
         <MEM memId="m99" CLM01="10"/>
         <MEM memId="m11" CLM01="10"/>
      </CUS>
   </VEN>
</Data>

<强>解释

  1. 双程转换。

  2. 第一次传递会添加假MEM元素,以便结果中的每个CUS元素都有MEM个孩子,其数量是$pSize的倍数。

  3. 第二遍:

  4. 使用并覆盖 identity rule

  5. 使用 <xsl:number> 通过MEM获取level="any"元素的正确编号。

答案 1 :(得分:1)

只是为了好玩,一次转换:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:param name="pSize" select="3"/>
    <xsl:template match="node()|@*">
        <xsl:param name="pOffset" select="0"/>
        <xsl:copy>
            <xsl:apply-templates select="node()|@*">
                <xsl:with-param name="pOffset" select="$pOffset"/>
                <xsl:with-param name="pPosition" select="position()"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="VEN|CUS">
        <xsl:param name="pOffset" select="0"/>
        <xsl:variable name="vIsVEN" select="self::VEN"/>
        <xsl:copy>
            <xsl:apply-templates
             select="@*|node()[position()=1 and $vIsVEN or not($vIsVEN)]">
                <xsl:with-param name="pOffset" select="$pOffset"/>
            </xsl:apply-templates>
        </xsl:copy>
        <xsl:apply-templates select="following-sibling::node()[1]">
            <xsl:with-param name="pOffset"
             select="$pOffset + count(.//MEM[position() mod $pSize = 1])"/>
        </xsl:apply-templates>
    </xsl:template>
    <xsl:template match="MEM/@CLM01">
        <xsl:param name="pPosition" select="1"/>
        <xsl:param name="pOffset" select="0"/>
        <xsl:attribute name="{name()}">
            <xsl:value-of 
             select="$pOffset + ceiling(($pPosition - 1) div $pSize)"/>
        </xsl:attribute>
    </xsl:template>
</xsl:stylesheet>

输出:

<Data>
    <VEN vendorId="v1">
        <CUS custId="c1">
            <MEM memId="m1" CLM01="1"></MEM>
            <MEM memId="m2" CLM01="1"></MEM>
            <MEM memId="m3" CLM01="1"></MEM>
            <MEM memId="m4" CLM01="2"></MEM>
            <MEM memId="m5" CLM01="2"></MEM>
        </CUS>
        <CUS custId="c2">
            <MEM memId="m11" CLM01="3"></MEM>
            <MEM memId="m12" CLM01="3"></MEM>
            <MEM memId="m13" CLM01="3"></MEM>
            <MEM memId="m14" CLM01="4"></MEM>
            <MEM memId="m15" CLM01="4"></MEM>
            <MEM memId="m16" CLM01="4"></MEM>
            <MEM memId="m17" CLM01="5"></MEM>
            <MEM memId="m18" CLM01="5"></MEM>
        </CUS>
    </VEN>
    <VEN vendorId="v2">
        <CUS custId="c1">
            <MEM memId="m4" CLM01="6"></MEM>
            <MEM memId="m5" CLM01="6"></MEM>
            <MEM memId="m6" CLM01="6"></MEM>
            <MEM memId="m7" CLM01="7"></MEM>
            <MEM memId="m8" CLM01="7"></MEM>
        </CUS>
        <CUS custId="c1">
            <MEM memId="m33" CLM01="8"></MEM>
            <MEM memId="m44" CLM01="8"></MEM>
            <MEM memId="m55" CLM01="8"></MEM>
            <MEM memId="m66" CLM01="9"></MEM>
            <MEM memId="m77" CLM01="9"></MEM>
            <MEM memId="m88" CLM01="9"></MEM>
            <MEM memId="m99" CLM01="10"></MEM>
            <MEM memId="m11" CLM01="10"></MEM>
        </CUS>
    </VEN>
    <VEN vendorId="v2">
        <CUS custId="c1">
            <MEM memId="m4" CLM01="1"></MEM>
            <MEM memId="m5" CLM01="1"></MEM>
            <MEM memId="m6" CLM01="1"></MEM>
            <MEM memId="m7" CLM01="2"></MEM>
            <MEM memId="m8" CLM01="2"></MEM>
        </CUS>
        <CUS custId="c1">
            <MEM memId="m33" CLM01="3"></MEM>
            <MEM memId="m44" CLM01="3"></MEM>
            <MEM memId="m55" CLM01="3"></MEM>
            <MEM memId="m66" CLM01="4"></MEM>
            <MEM memId="m77" CLM01="4"></MEM>
            <MEM memId="m88" CLM01="4"></MEM>
            <MEM memId="m99" CLM01="5"></MEM>
            <MEM memId="m11" CLM01="5"></MEM>
        </CUS>
    </VEN>
</Data>

注意:混合儿童和兄弟姐妹遍历。隧道参数。