2011-04-20 75 views
1

我需要一些关于此XSLT的帮助。它的工作方式是假设我的需求发生了变化... :-),并且我需要修改它来给我预期的输出。 我正在寻找一些指导和帮助。带有多个集合的XSLT分组

说明: 我有一个源XML这样

<XML> 
    <Attributes> 
    <Attribute> 
    <Name/> 
    <Type/> 
    <Value/> 
    <FromIM/> 
    <collection/> 
     <Path /> 
    </Attribute> 
</Attributes> 
</XML> 

在上述XML我需要看节点“类型”,并将它们组由类型。例如,如果我有5个属性,其中Type是常见的,4个属性(其中Type是类别),以及3个属性(其中Type是Complex),则将它们按照这种方式分组。

<?xml version="1.0" encoding="utf-8"?> 
<Data Schema="XML A"> 
    <Items> 
    <Item id="" shortname="FT123" longname="FT123" categorypath="FamilyName//DepartmentName//GroupName" type="Product"> 
     <Attributes type="common"> 
     <Attr name="common 1" value="1" path=""/> 
     <Attr name="common 2" value="2" path=""/> 
     <Attr name="common 3" value="3" path=""/> 
     <Attr name="common 4" value="4" path=""/> 
     <Attr name="common 5" value="4" path=""/> 
     <Collection id="" name="Collection" path=""> 
      <Complex> 
      <Attr name="UPC" value="Testing" valueKey="0" /> 
      <Attr name="Color" value="Yellow" valueKey="0"/> 
      <Attr name="Size" value="10" valueKey="0"/> 
      </Complex> 
     </Collection> 
     </Attributes> 
     <Attributes type="category"> 
     <Attr name="category1" value="1" /> 
     <Attr name="category2" value="2" /> 
     <Attr name="category3" value="3" /> 
     <Attr name="category4" value="4" /> 
     </Attributes> 
    </Item> 
    </Items> 
</Data> 

正如你可以从上面看到我组第一共用&类别和创造下常见的复杂的一组集合。这工作正常(虽然我使用迭代... :-))

问题是我创建一个复杂的只有一个属性,其中名称=集合,它是硬编码。但是,新的要求是我为名称=成本的另一个属性创建了一个复杂的集合。

这是我遇到问题的地方。我怎样才能做到这一点。以下是示例源代码和输出xml和XSLT。提前致谢。

源XML:

<?xml version="1.0" encoding="Windows-1252"?> 
<XML> 
    <Attributes> 
    <Attribute> 
     <Name>FamilyName</Name> 
     <Type>common</Type> 
     <Value>Footwear</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>DepartmentName</Name> 
     <Type>common</Type> 
     <Value>Footwear</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>GroupName</Name> 
     <Type>common</Type> 
     <Value>Men's Boots</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Buyer ID</Name> 
     <Type>common</Type> 
     <Value>Lee</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Enviornment</Name> 
     <Type>common</Type> 
     <Value>Dev</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Retail</Name> 
     <Type>common</Type> 
     <Value></Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Gender</Name> 
     <Type>category</Type> 
     <Value>M</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Cost</Name> 
     <Type>Complex</Type> 
     <Value>20.00</Value> 
     <FromIM>yes</FromIM> 
     <collection>Y</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Collection</Name> 
     <Type>Complex</Type> 
     <Value>ing</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>UPC</Name> 
     <Type>Complex</Type> 
     <Value>Testing</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Color</Name> 
     <Type>Complex</Type> 
     <Value>Yellow</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Size</Name> 
     <Type>Complex</Type> 
     <Value>10</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Style</Name> 
     <Type>Complex</Type> 
     <Value>MA</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>UPC</Name> 
     <Type>Complex</Type> 
     <Value>24a</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Color</Name> 
     <Type>Complex</Type> 
     <Value>Green</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Size</Name> 
     <Type>Complex</Type> 
     <Value>22</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    <Attribute> 
     <Name>Style</Name> 
     <Type>Complex</Type> 
     <Value>AM</Value> 
     <FromIM>no</FromIM> 
     <collection>N</collection> 
     <Path /> 
    </Attribute> 
    </Attributes> 
</XML> 

预期输出: 我需要2个集节点也日期我需要把当前的日期。 收集节点中的注意事项我可以有多个复杂节点。但是,在成本中,我将只有1个复杂节点。

<?xml version="1.0" encoding="utf-8"?> 
<Data Schema="XML A"> 
    <Items> 
    <Item id="" shortname="FT123" longname="FT123" sku="FT123" action="ADD" categorypath="FamilyName//DepartmentName//GroupName" type="Product"> 
     <Attributes type="common"> 
     <Attr name="Buyer ID" value="Lee" path="" action="ADD" /> 
     <Attr name="Enviornment" value="Dev" path="" action="ADD" /> 
     <Attr name="Retail" value="" path="" action="ADD" /> 
     <Collection id="" name="Collection" path=""> 
      <Complex> 
      <Attr name="UPC" value="Testing" valueKey="0" /> 
      <Attr name="Color" value="Yellow" valueKey="0"/> 
      <Attr name="Size" value="10" valueKey="0"/> 
      <Attr name="Style" value="MA" valueKey="0"/> 
      </Complex> 
      <Complex> 
      <Attr name="UPC" value="24a" valueKey="0"/> 
      <Attr name="Color" value="Green" valueKey="0"/> 
      <Attr name="Size" value="22" valueKey="0"/> 
      <Attr name="Style" value="AM" valueKey="0"/> 
      </Complex> 
     </Collection> 
     <Collection id="" name="Cost" path=""> 
      <Complex> 
      <Attr name="Cost" value="22" valueKey="0" /> 
      <Attr name="Date" value="" valueKey="0"/> 
      </Complex> 
     </Collection> 
     </Attributes> 
     <Attributes type="category"> 
     <Attr name="Gender" value="M" /> 
     </Attributes> 
    </Item> 
    </Items> 
</Data> 

XSLT:根据迈克尔的评论

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="type" match="Attribute" use="Type"/> 
    <xsl:template match="/"> 
    <Data Schema="XML A"> 
     <Items> 
     <Item> 
      <xsl:variable name="fileName" select="XML/Attributes/Attribute[Name = 'PIFileNumber']/Value"/> 

      <xsl:attribute name="id"></xsl:attribute> 
      <xsl:attribute name="shortname"> 
      <xsl:value-of select="$fileName"/> 
      </xsl:attribute> 
      <xsl:attribute name="longname"> 
      <xsl:value-of select="$fileName"/> 
      </xsl:attribute> 

      <xsl:variable name="familyName" select="XML/Attributes/Attribute[Name = 'FamilyName'/id"/> 
      <xsl:variable name="deptName" select="XML/Attributes/Attribute[Name = 'DepartmentName']/id"/> 
      <xsl:variable name="groupName" select="XML/Attributes/Attribute[Name = 'GroupName']/id"/> 
      <xsl:variable name="catPath" select="concat($familyName,'//',$deptName,'//',$groupName)" /> 

      <xsl:attribute name="categorypath" select="$catPath"/> 
      <xsl:attribute name="type">Product</xsl:attribute> 
      <xsl:apply-templates select="XML/Attributes/Attribute[generate-id() = generate-id(key('type', Type)[1])]"> 
      <xsl:sort select="Type" order="descending"/> 
      </xsl:apply-templates> 
     </Item> 
     </Items> 
    </Data> 
    </xsl:template> 
    <xsl:template match="Attribute"> 
    <xsl:variable name="compType" select="count(/XML/Attributes/Attribute[Type='Complex' and Name!='Collection'])"/> 
    <xsl:variable name="colid" select="/XML/Attributes/Attribute[Name = 'Collection']/id"/> 
    <xsl:variable name="colname" select="/XML/Attributes/Attribute[Name = 'Collection']/Name"/> 
    <xsl:variable name="colpath" select="/XML/Attributes/Attribute[Name = 'Collection']/Path"/> 

    <xsl:if test="Type!='Complex'"> 
     <Attributes type="{Type}"> 
     <xsl:apply-templates select="key('type',Type)" mode="out"/> 
     <xsl:if test="Type='common'"> 
      <Collection id="{$colid}" name="{$colname}" path="{$colpath}" action="ADD"> 
      <xsl:choose> 
       <xsl:when test="$compType > 0"> 
       <xsl:call-template name="for.loop"> 
        <xsl:with-param name="i">1</xsl:with-param> 
        <xsl:with-param name="count" select="count(/XML/Attributes/Attribute[Type='Complex' and Name='UPC'])" /> 
       </xsl:call-template> 
       </xsl:when> 
       <xsl:otherwise> 
       <Complex refId="0"> 
        <MaskValue /> 
        <Attr id="" name="UPC" value="" valueKey="0"/> 
        <xsl:choose> 
        <xsl:when test="count(/XML/Attributes/Attribute[Name = 'Color']) > 0"> 
         <Attr id="{//Attribute[Name = 'Color']/id}" name="Color" value="{//Attribute[Name = 'Color']/Value}" valueKey="0"/> 
        </xsl:when> 
        <xsl:otherwise> 
         <Attr id="" name="Color" value="Default" valueKey="0"/> 
        </xsl:otherwise> 
        </xsl:choose> 
        <xsl:choose> 
        <xsl:when test="count(/XML/Attributes/Attribute[Name = 'Size']) > 0"> 
         <Attr id="{//Attribute[Name = 'Size']/id}" name="Color" value="{//Attribute[Name = 'Size']/Value}" valueKey="0"/> 
        </xsl:when> 
        <xsl:otherwise> 
         <Attr id="" name="Size" value="Default" valueKey="0"/> 
        </xsl:otherwise> 
        </xsl:choose> 
        <Attr id="" name="Style" value="" valueKey="0"/> 
        <Attr id="" name="Exclude" value="0" valueKey="0"/> 
       </Complex> 
       </xsl:otherwise> 
      </xsl:choose> 
      </Collection> 
     </xsl:if> 
     </Attributes> 
    </xsl:if> 
    </xsl:template> 
    <xsl:template match="Attribute" mode="out"> 
    <xsl:if test="FromIM = 'yes'"> 
     <xsl:choose> 
     <xsl:when test="collection = 'Y' and Name!='Color' and Name!='Size'"> 
      <Collection id="" name="{Name}" path="{Path}"> 
      <Attr value="{Value}" uom="" locale="en_WW"/> 
      </Collection> 
     </xsl:when> 
     <xsl:otherwise> 
      <xsl:if test="Name!='FileNumber' and Name!='NotReqInIM' and Name!='Color' and Name!='Size'"> 
      <Attr id="{id}" name="{Name}" value="{Value}" path="{Path}" action="ADD" uom="" Locale="en_WW"/> 
      </xsl:if> 
     </xsl:otherwise> 
     </xsl:choose> 
    </xsl:if> 
    </xsl:template> 
    <xsl:template match="Attribute[Type='Complex']" mode="out"> 
    <xsl:if test="Name!='Collection'"> 
     <Attr id="{id}" name="{Name}" value="{Value}" valueKey="0"/> 
    </xsl:if> 
    </xsl:template> 


    <!-- this is for loop code --> 
    <xsl:template name="for.loop"> 
    <xsl:param name="i" /> 
    <xsl:param name="count" /> 
    <!--begin_: Line_by_Line_Output --> 
    <xsl:if test="$i &lt;= $count"> 
     <xsl:if test="Name!='Collection'"> 
     <Complex refId="0"> 
      <MaskValue /> 
      <Attr id="{(//Attribute[Type='Complex' and Name = 'UPC'])[position() = $i]/id}" name="UPC" value="{(//Attribute[Type='Complex' and Name = 'UPC'])[position() = $i]/Value}" valueKey="0"/> 
    <Attr id="{(//Attribute[Type='Complex' and Name = 'Color'])[position() = $i]/id}" name="Color" value="{(//Attribute[Type='Complex' and Name = 'Color'])[position() = $i]/Value}" valueKey="0"/> 
    <Attr id="{(//Attribute[Type='Complex' and Name = 'Size'])[position() = $i]/id}" name="Size" value="{(//Attribute[Type='Complex' and Name = 'Size'])[position() = $i]/Value}" valueKey="0"/> 
    <Attr id="{(//Attribute[Type='Complex' and Name = 'Style'])[position() = $i]/id}" name="Style" value="{(//Attribute[Type='Complex' and Name = 'Style'])[position() = $i]/Value}" valueKey="0"/> 
    <Attr id="0" name="Exclude" value="0" valueKey="0"/> 
     </Complex> 
     </xsl:if> 
    </xsl:if> 

    <!--begin_: RepeatTheLoopUntilFinished--> 
    <xsl:if test="$i &lt;= $count"> 
     <xsl:call-template name="for.loop"> 
     <xsl:with-param name="i"> 
      <xsl:value-of select="$i + 1"/> 
     </xsl:with-param> 
     <xsl:with-param name="count"> 
      <xsl:value-of select="$count"/> 
     </xsl:with-param> 
     </xsl:call-template> 
    </xsl:if> 

    </xsl:template> 
</xsl:stylesheet> 
+1

您的代码会更容易阅读'<集合名称= “{NAME}” 路径= “{PATH}”/>'。在一些变量中有很多不必要的冗长,例如您可以将colname初始化为' – 2011-04-21 09:26:29

+0

@Michael。感谢您的答复。根据您对变量初始化的评论,我修改了XSLT。但是,我不明白你的意思是使用属性值模板。你能解释一下吗?谢谢 – JohnXsl 2011-04-21 14:04:07

回答

0

虽然远非完美,这里是一个样式表,它会产生你想要的输出更新。我不确定每个复合物的属性固定的程度或集合是固定的。让我知道这是否有帮助。 attribute`:如果您使用,而不是`XSL属性值模板

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/> 
    <xsl:key name="type" match="Attribute" use="Type"/> 
    <xsl:template match="/"> 
     <Data Schema="XML A"> 
      <Items> 
       <Item> 
        <xsl:variable name="fileName" select="XML/Attributes/Attribute/Name['PIFileNumber']/Value"/> 
        <xsl:attribute name="id"></xsl:attribute> 
        <xsl:attribute name="shortname"> 
         <xsl:value-of select="$fileName"/> 
        </xsl:attribute> 
        <xsl:attribute name="longname"> 
         <xsl:value-of select="$fileName"/> 
        </xsl:attribute> 
        <xsl:variable name="familyName" select="XML/Attributes/Attribute[Name='FamilyName']/Value"/> 
        <xsl:variable name="deptName" select="XML/Attributes/Attribute[Name='DepartmentName']/Value"/> 
        <xsl:variable name="groupName" select="XML/Attributes/Attribute[Name='GroupName']/Value"/> 
        <xsl:variable name="catPath" select="concat($familyName,'//',$deptName,'//',$groupName)" /> 
        <xsl:attribute name="categorypath"> 
         <xsl:value-of select="$catPath"/> 
        </xsl:attribute> 
        <xsl:attribute name="type">Product</xsl:attribute> 
        <xsl:apply-templates select="XML/Attributes/Attribute[generate-id() = generate-id(key('type', Type)[1])]"> 
         <xsl:sort select="Type" order="descending"/> 
        </xsl:apply-templates> 
       </Item> 
      </Items> 
     </Data> 
    </xsl:template> 
    <xsl:template match="Attribute" mode="Collection"> 
     <Collection id="" name='Collection'> 
      <xsl:apply-templates select="../Attribute[Name='Collection']" mode="Coll"/> 
     </Collection> 
     <Collection id="" name='Cost'> 
      <xsl:apply-templates select="../Attribute[Name='Cost']" mode="Cost"/> 
     </Collection> 
    </xsl:template> 
    <xsl:template match="Attribute[Type='Complex']"/> 
    <xsl:template match="Attribute[Type != 'Complex']"> 
     <Attributes type="{Type}"> 
      <xsl:variable name="Type" select="Type"/> 
      <xsl:apply-templates select="../Attribute[Type=$Type]" mode="Attr"/> 
      <xsl:if test="Type='common'"> 
       <xsl:apply-templates select="." mode="Collection"/> 
      </xsl:if> 
     </Attributes> 
    </xsl:template> 
    <xsl:template match="Attribute" mode="Coll"> 
     <xsl:apply-templates select="../Attribute[Name='UPC']" mode="UPC"/> 
    </xsl:template> 
    <xsl:template match="Attribute" mode="Cost"> 
     <complex> 
      <Attr name="Cost" value="{../Attribute[Name='Cost']/Value}" valueKey="0"/> 
      <Attr name="Date" value="" valueKey="0"/> 
     </complex> 
    </xsl:template> 
    <xsl:template match="Attribute" mode="Attr"> 
     <Attr name="{Name}" value="{Value}" valueKey="0"/> 
    </xsl:template> 
    <xsl:template match="Attribute" mode="UPC"> 
     <complex> 
      <Attr name="UPC" value="{Value}" valueKey="0"/> 
      <Attr name="Color" value="{following::node()[Name='Color']/Value}" valueKey="0"/> 
      <Attr name="Size" value="{following::node()[Name='Size']/Value}" valueKey="0"/> 
      <Attr name="Style" value="{following::node()[Name='Style']/Value}" valueKey="0"/> 
     </complex> 
    </xsl:template> 
</xsl:stylesheet>