开发者

XSLT combine node when attribute's value are different

During transformation, who I can combine one node into another. for example, when Attributes/Attribute/Type=ComplexAttr then it should go under Attributes/Attribute/Type=Common only. Below is the sample XML & XSLT that I'm trying to use which is not working. TIA (Thanks in Advance)

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="type" match="Attribute" use="Type"/>
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates select="XML/Attributes/Attribute">
                <xsl:sort select="Type" order="descending"/>
            </xsl:apply-templates>
            <errorCodes>
                <xsl:apply-templates select="XML/Attributes/Attribute"
                                     mode="errors"/>
            </errorCodes>
        </Data>
    </xsl:template>
    <xsl:template
            match="Attribute[generate-id()=generate-id(key('type', Type)[1])]">
        <xsl:if test="Type != 'ComplexAttr'">
            <Attributes type="{Type}">
                <xsl:if test="Type = 'ComplexAttr'">
                    <xsl:value-of select="Common"/>
                </xsl:if>
                <xsl:apply-templates select="../Attribute[Type=current()/Type]" mode="out"/>
            </Attributes>           
        </xsl:if>
    </xsl:template>
    <xsl:template match="Attribute" mode="out">
        <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute"/>
    <xsl:template match="Attribute" mode="errors"/>
    <xsl:template match="Attribute[Value='']" mode="errors">
        <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
    </xsl:template>
    <xsl:template match="/Attribute">
        <xsl:if test="Type = 'ComplexAttr'">
            <Attributes type="Common">
                <xsl:apply-templates select="../Attribute[Type=current()/Type]" mode="out"/>
                <!--<Attr id="{id}" name="{Name}" value="{Value}"/>-->
            </Attributes>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

---- Source XML ----

<?xml version="1.0" encoding="windows-1252"?>
<XML>
    <Attributes>
        <Attribute>
            <id>5</id>
            <Name>Buyer ID</Name>
            <Type>common</Type>
            <Value>Lee</Value>
        </Attribute>
        <Attribute>
            <id>331</id>
            <Name>Enviornment</Name>
            <Type>common</Type>
            <Value>Development</Value>
        </Attribute>
        <Attribute>
            <id>79</id>
            <Name>Retail</Name>
            <Type>common</Type>
            <Valu开发者_如何学运维e></Value>
        </Attribute>
        <Attribute>
            <id>402</id>
            <Name>Gender</Name>
            <Type>category</Type>
            <Value>Men</Value>
        </Attribute>
    <Attribute>
         <id>1197</id> 
         <Name>UPC</Name> 
         <Type>ComplexAttr</Type> 
         <Value>Testing</Value> 
         <Path /> 
    </Attribute>
    </Attributes>
</XML>

---- Transformed XML output

<?xml version="1.0" encoding="utf-8"?>
<Data Schema="XML A">
  <Attributes type="common">
    <Attr id="5" name="Buyer ID" value="Lee" />
    <Attr id="331" name="Enviornment" value="Development" />
    <Attr id="79" name="Retail" value="" />
    <Attr id="41" name="PlusShip" value="False" />
    <Collection id="" name="test">
      <ComplexAttr refId="0">
        <MaskValue />
        <Attr id="1197" name="UPC" value="Testing" />
      </ComplexAttr>
    </Collection>
  </Attributes>
  <Attributes type="category">
    <Attr id="402" name="Gender" value="Men" />
    <Attr id="433" name="HeelHeight" value="" />
  </Attributes>
  <errorCodes>
    <errorCode>"value for Retail is missing."</errorCode>
  </errorCodes>
</Data>


If you want to group Attribute by Type with 'common' and 'ComplexAttr' in the same group, then you need to change the key value expression into something like:

<xsl:key name="type" 
         match="Attribute" 
         use="concat(
                 Type[. != 'ComplexAttr'],
                 substring(
                    'common',
                    1 div (Type = 'ComplexAttr')
                 )
              )"/> 

<xsl:template match="Attribute[
                        generate-id()
                         = generate-id(
                              key('type',
                                  concat(
                                     Type[. != 'ComplexAttr'],
                                     substring(
                                        'common',
                                        1 div (Type = 'ComplexAttr')
                                     )
                                  )
                              )[1]
                           )
                     ]">       

EDIT: And in the group templates applying:

<xsl:apply-templates select="key('type',
                                 concat(
                                    Type[. != 'ComplexAttr'],
                                    substring(
                                       'common',
                                       1 div (Type = 'ComplexAttr')
                                    )
                                 )
                             )" 
                     mode="out"/> 

EDIT: Full example. This stylesheet:

<!DOCTYPE xsl:stylesheet [
<!ENTITY key "concat(Type[. != 'ComplexAttr'],substring('common',1 div (Type = 'ComplexAttr')))">
]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:key name="type" match="Attribute" use="&key;"/>
    <xsl:template match="/">
        <Data Schema="XML A">
            <xsl:apply-templates
                 select="XML/Attributes/Attribute[
                            generate-id() = generate-id(key('type', &key;)[1])
                         ]">
                <xsl:sort select="&key;" order="descending"/>
            </xsl:apply-templates>
            <errorCodes>
                <xsl:apply-templates select="XML/Attributes/Attribute"
                                     mode="errors"/>
            </errorCodes>
        </Data>
    </xsl:template>
    <xsl:template match="Attribute">
        <xsl:variable name="vCurrent-Grouping-Key" select="&key;"/>
        <Attributes type="{$vCurrent-Grouping-Key}">
            <xsl:apply-templates select="key('type',$vCurrent-Grouping-Key)"
                                 mode="out"/>
        </Attributes>
    </xsl:template>
    <xsl:template match="Attribute" mode="out" name="makeAttr">
        <Attr id="{id}" name="{Name}" value="{Value}"/>
    </xsl:template>
    <xsl:template match="Attribute[Type='ComplexAttr']" mode="out">
        <Collection id="" name="test">
            <ComplexAttr refId="0">
                <MaskValue />
                <xsl:call-template name="makeAttr"/>
            </ComplexAttr>
        </Collection>
    </xsl:template>
    <xsl:template match="Attribute" mode="errors"/>
    <xsl:template match="Attribute[Value='']" mode="errors">
        <errorCode>"value for <xsl:value-of select="Name"/> is missing."</errorCode>
    </xsl:template>
</xsl:stylesheet>

Output:

<Data Schema="XML A">
    <Attributes type="common">
        <Attr id="5" name="Buyer ID" value="Lee" />
        <Attr id="331" name="Enviornment" value="Development" />
        <Attr id="79" name="Retail" value="" />
        <Collection id="" name="test">
            <ComplexAttr refId="0">
                <MaskValue />
                <Attr id="1197" name="UPC" value="Testing" />
            </ComplexAttr>
        </Collection>
    </Attributes>
    <Attributes type="category">
        <Attr id="402" name="Gender" value="Men" />
    </Attributes>
    <errorCodes>
        <errorCode>"value for Retail is missing."</errorCode>
    </errorCodes>
</Data>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜