Re: [xsl] Combining of nested children

Subject: Re: [xsl] Combining of nested children
From: "Mark" <mark@xxxxxxxxxxxx>
Date: Wed, 5 Sep 2012 22:29:37 -0700
Syd,
Thanks for your suggestions. As you can see, the requirements are a bit more complex than in the example I sent
Here is the code I worked out that works for <Heading> but not at the nested <SubDiv1> level.
I get a "multiple-argument for concat" at the second level in this template.
I suspect I am doing something stupid, but not sure what the arguments of the second for-each-group should be.
Mark


<xsl:param name=" sorting-collation" select="'http://www.w3.org/2005/xpath-functions/collation/codepoint'"/>
<!--<xsl:param name=" sorting-collation" select="'http://saxon.sf.net/collation?class=CzechCollation'"/>-->


<xsl:template match="List">
<List>
<!-- Group by Heading -->
<!-- The ' ' separator between Heading and Heading/@entry insures proper sorting -->
<xsl:for-each-group select="Item" group-by="concat(Heading/@data, Heading/@catalog, Heading/@scott-number, Heading/@pofis-number,' ',Heading/@entry) " collation="{$sorting-collation}">
<xsl:sort select="current-grouping-key()" collation="{$sorting-collation}"/>
<Item>
<Heading>
<xsl:copy-of select="current-group()/Heading/@*"/>
<xsl:copy-of select="current-group()/Heading/ToRef"/>
<xsl:copy-of select="current-group()/Heading/Article"/>


<!-- <xsl:copy-of select="Heading/SubDiv1"/> Ignore this line it substitutes for the code below without inserting the <ToRef>-->

<!-- This is failing
<xsl:for-each-group select="current-group()" group-by="concat(Heading/SubDiv1/@data, Heading/SubDiv1/@catalog, Heading/SubDiv1/@scott-number, Heading/SubDiv1/@pofis-number)">
<xsl:sort select="current-grouping-key()" collation="{$sorting-collation}"/>
<xsl:if test="Heading/SubDiv1">
<xsl:element name="SubDiv1">
<xsl:copy-of select="current()/Heading/SubDiv1/@*"/>
<xsl:copy-of select="current-group()/Heading/SubDiv1/ToRef"/>
<xsl:copy-of select="current-group()/Heading/SubDiv1/Article"/>
<xsl:copy-of select="Heading/SubDiv1/SubDiv2"/>
</xsl:element>
</xsl:if>
</xsl:for-each-group>
-->
</Heading>
</Item>
</xsl:for-each-group>
</List>
</xsl:template>


-----Original Message----- From: Syd Bauman
Sent: Wednesday, September 05, 2012 9:28 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Combining of nested children


Not sure I understand the requirements completely, but given your
input, the following does produce the desired output.

---------
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
xmlns:xs="http://www.w3.org/2001/XMLSchema"; exclude-result-prefixes="xs" version="2.0">


 <!-- standard easy-to-write identity template -->
 <xsl:template match="@*|node()">
   <xsl:copy>
     <xsl:apply-templates select="@*|node()"/>
   </xsl:copy>
 </xsl:template>

<!-- process a heading that has an @id specially: -->
<xsl:template match="Heading[@id]">
<xsl:copy>
<!-- first, process my attributes -->
<xsl:apply-templates select="@*"/>
<!-- then, copy over desired <ToRef> -->
<xsl:apply-templates
select="../../Item/Heading[ not(@id) and @entry = current()/@entry and @data eq current()/@data ]/ToRef"/>
<!-- last, process my children -->
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>


<!-- ignore <Item>s that have <Heading>s from which we already took the <ToRef> -->
<!-- (Note that this code does not check to see that we actually took or will -->
<!-- take the <ToRef> ? rather it just tests if there is no id= attr, and figures -->
<!-- that if there is not an id=, then the entry= and data= must have matched. -->
<xsl:template match="Item[Heading[not(@id)]]"/>


</xsl:stylesheet>
---------


I need to find <Items> in a <List> that have an identical <Heading>
attributes except for the @id, and insert a <ToRefs> element from
the <Item> without an @id into the <Item> that has the @id
attribute. Sample input and output <Item>s are shown below.

I will need to do the same sort of insertion at the <SubDiv1>
level, or at the two other possible nested levels of <SubDiv2> and
<SubDiv3> [not shown].

I will try to figure out how to do those latter cases once I
understand how to do the <Headings> case.

Any help appreciated,

Input:

<List>
<Item>
<Heading id="A4" entry="subject" data="Abolition of Serfdom">
<SubDiv1 id="A4-1" catalog="1" scott-number="350" pofis-number="474"
data="1948. 100th Anniversary of Abolition">
<Article>
<Person>Bulletin of the Ministry of Posts</Person>
<Title>New issues [Title varies or absent]</Title>
</Article>
</SubDiv1>
</Heading>
</Item>
<Item>
<Heading entry="subject" data="Abolition of Serfdom">
<ToRef xref="See also" data="Slovakia - Peasant Revolt 1848" file="s"
block="A1272-21"/>
</Heading>
</Item>
</List>

Output:
<List>
<Item>
<Heading id="A4" entry="subject" data="Abolition of Serfdom">
<ToRef xref="See also" data="Slovakia - Peasant Revolt 1848" file="s"
block="A1272-21"/>
<SubDiv1 id="A4-1" catalog="1" scott-number="350" pofis-number="474"
data="1948. 100th Anniversary of Abolition">
<Article>
<Person>Bulletin of the Ministry of Posts</Person>
<Title>New issues [Title varies or absent]</Title>
</Article>
</SubDiv1>
</Heading>
</Item>

Current Thread