2011-04-20 68 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>