xml - Complex Grouping using XSLT 1.0 -


i've revised data file , added grouping column. not figure out logic grouping otherwise.

the data contains information stamp collection.

here sample xml:

<?xml version="1.0" encoding="utf-8"?> <stamps>         <stamp>      <group>25</group>        <scott>3133</scott>      <title>32¢ thornton wilder</title>       <series>literary arts</series>       </stamp>         <stamp>      <group>26</group>        <scott>3134</scott>      <title>32¢ charlie chaplin</title>       </stamp> <stamp>      <group>26</group>        <scott>3135</scott>      <title>32¢ raoul wallenberg</title>      </stamp> <stamp>      <group>27</group>        <scott>3136</scott>      <title>sheet of 15</title>       <issue>the world of dinosaurs</issue>        </stamp>         <stamp>      <group>27</group>        <scott>3136</scott>      <minor>a</minor>         <title>32¢ ceratosaurus</title>      <issue>the world of dinosaurs</issue>        </stamp>         <stamp>      <group>27</group>        <scott>3136</scott>      <minor>b</minor>         <title>32¢ camptosaurus</title>      <issue>the world of dinosaurs</issue>        </stamp>         <stamp>      <group>27</group>        <scott>3136</scott>      <minor>c</minor>         <title>32¢ camarasaurus</title>      <issue>the world of dinosaurs</issue>        </stamp></stamps> 

here xslt put together:

<?xml version="1.0" encoding="utf-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" indent="yes"/>  <xsl:key name="stampgroup" match="stamp" use="group"/> <xsl:key name="scottgroup" match="stamp" use="concat(group, '|', scott)"/>  <xsl:template match="/*">  <xsl:copy>   <xsl:apply-templates select="stamp[generate-id() = generate-id(key('stampgroup', group)[1])]" mode="stampgroup" />  </xsl:copy>  </xsl:template>  <xsl:template match="stamp" mode="stampgroup"> <stampgroup id="{group}">          <xsl:apply-templates select="key('stampgroup', group)[generate-id() = generate-id(key('scottgroup', concat(group, '|', scott))[1])]" mode="scottgroup" /> </stampgroup> </xsl:template>  <xsl:template match="stamp" mode="scottgroup">  <stamp>   <scott><xsl:value-of select="scott"/></scott>   <title><xsl:value-of select="title"/></title>   <minor><xsl:value-of select="minor"/></minor>   </stamp> </xsl:template>  </xsl:stylesheet> 

here resulting xml:

<?xml version="1.0" encoding="utf-8"?> <stamps> <stampgroup id="25">   <stamp>      <scott>3133</scott>      <title>32¢ thornton wilder</title>      <minor/>   </stamp> </stampgroup> <stampgroup id="26">   <stamp>      <scott>3134</scott>      <title>32¢ charlie chaplin</title>      <minor/>   </stamp>   <stamp>      <scott>3135</scott>      <title>32¢ raoul wallenberg</title>      <minor/>    </stamp>   <stamp>      <scott>3136</scott>      <title>sheet of 15</title>      <minor/>   </stamp>  </stampgroup> </stamps> 

it's working. it's pulling groups. it's pulling unique <scott> items, it's not picking <minor> subitems.

i've never used type of xslt structure before. how repeat items in for-each?

group 27 has 4 items in it. have same <scott> number different <minor> fields.

do need create third key?

sorry, forgot add desired result:

<?xml version="1.0" encoding="utf-8"?> <stamps> <stampgroup id="25">   <stamp>      <scott>3133</scott>      <title>32¢ thornton wilder</title>      <minor/>   </stamp> </stampgroup> <stampgroup id="26">   <stamp>      <scott>3134</scott>      <title>32¢ charlie chaplin</title>      <minor/>   </stamp>   <stamp>      <scott>3135</scott>      <title>32¢ raoul wallenberg</title>      <minor/>   </stamp> </stampgroup> <stampgroup id="27">   <stamp>      <scott>3136</scott>      <title>sheet of 15</title>      <minor/>   </stamp>   <stamp>      <scott>3136</scott>      <title>32¢ ceratosaurus</title>      <minor>a</minor>          </stamp>   <stamp>      <scott>3136</scott>      <title>32¢ camptosaurus</title>          <minor>b</minor>          </stamp>   <stamp>      <scott>3136</scott>      <title>32¢ camarasaurus</title>      <minor>c</minor>          </stamp>  </stampgroup> </stamps> 

if want have unique scott values within each group, , unique minor values within each scott subgroup, yes, need 3 keys.

and if values want subgroup not unique each parent group, keys have concatenated in order narrow key down matching items current parent group only.

xslt 1.0

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/>  <xsl:key name="stamp-by-group" match="stamp" use="group" /> <xsl:key name="stamp-by-scott" match="stamp" use="concat(group, '|', scott)" /> <xsl:key name="stamp-by-minor" match="stamp" use="concat(group, '|', scott, '|', minor)" />  <xsl:template match="/stamps">     <xsl:copy>         <xsl:for-each select="stamp[count(. | key('stamp-by-group', group)[1]) = 1]">             <stampgroup id="{group}">                 <xsl:for-each select="key('stamp-by-group', group)[count(. | key('stamp-by-scott', concat(group, '|', scott))[1]) = 1]">                     <xsl:apply-templates select="key('stamp-by-scott', concat(group, '|', scott))[count(. | key('stamp-by-minor', concat(group, '|', scott, '|', minor))[1]) = 1]"/>                 </xsl:for-each>             </stampgroup>         </xsl:for-each>     </xsl:copy> </xsl:template>  <xsl:template match="stamp">     <xsl:copy>         <xsl:copy-of select="scott | title"/>         <minor><xsl:value-of select="minor" /></minor>     </xsl:copy> </xsl:template>  </xsl:stylesheet> 

edit:

if you're not creating group scott, can skip secondary grouping , associated key, , go directly tertiary grouping:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/xsl/transform"> <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/> <xsl:strip-space elements="*"/>  <xsl:key name="stamp-by-group" match="stamp" use="group" /> <xsl:key name="stamp-by-minor" match="stamp" use="concat(group, '|', scott, '|', minor)" />  <xsl:template match="/stamps">     <xsl:copy>         <xsl:for-each select="stamp[count(. | key('stamp-by-group', group)[1]) = 1]">             <stampgroup id="{group}">                 <xsl:apply-templates select="key('stamp-by-group', group)[count(. | key('stamp-by-minor', concat(group, '|', scott, '|', minor))[1]) = 1]"/>             </stampgroup>         </xsl:for-each>     </xsl:copy> </xsl:template>  <xsl:template match="stamp">     <xsl:copy>         <xsl:copy-of select="scott | title"/>         <minor><xsl:value-of select="minor" /></minor>     </xsl:copy> </xsl:template>  </xsl:stylesheet> 

Comments

Popular posts from this blog

python - TypeError: start must be a integer -

c# - DevExpress RepositoryItemComboBox BackColor property ignored -

django - Creating multiple model instances in DRF3 -