Re: [xsl] Want to process child and decendent nodes the same way as parent node but can only process children

Subject: Re: [xsl] Want to process child and decendent nodes the same way as parent node but can only process children
From: "Eliot Kimber ekimber@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 16 Dec 2014 15:11:04 -0000
Note that the DITA Community organization on GitHub
(www.dita-community.org) provides general code for working with DITA
source. The project org.dita-community.common.xslt
(https://github.com/dita-community/org.dita-community.common.xslt)
provides two libraries, relpath_util.xsl and dita-support-lib.xsl, that
support pretty much anything you need to do with DITA in terms of
resolving references, working with maps and topicrefs, and so on.

Other projects under DITA Community provide examples of more involved DITA
processing. The DITA for Publishers project (www.dita4publishers.org)
provides addition libraries and code samples. In particular, it provides
the "map-drive processing" framework for working with maps and the things
they reference.

Cheers,

Eliot
bbbbb
Eliot Kimber, Owner
Contrext, LLC
http://contrext.com




On 12/15/14, 6:30 PM, "Jason Davis nosaj3@xxxxxxxxx"
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:

>Sorry, I didn't post my style sheet in its entirety.
>
><xsl:stylesheet version="2.0"
>xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
>
>    <xsl:output method="xml" encoding="UTF-8" indent="yes"/>
>
>    <xsl:strip-space elements="*"/>
>
>    <xsl:key name="proc-num" match="map" use="keydef/@keys"/>
>
>    <xsl:template match="/directory">
>        <service-manual>
>            <xsl:apply-templates select="file"/>
>        </service-manual>
>    </xsl:template>
>
>    <xsl:template match="file">
>        <xsl:variable name="path" select="@name"/>
>        <xsl:for-each select="document($path)/task">
>            <procedure>
>                <name>
>                    <xsl:value-of select="title"/>
>                </name>
>                <frt-num>
>                    <xsl:value-of select="substring-after(@id,'X')"/>
>                </frt-num>
>                <xsl:apply-templates/>
>            </procedure>
>        </xsl:for-each>
>    </xsl:template>
>
>    <xsl:template match="//cmd/xref">
>        <xsl:variable name="matching-proc" select="key('proc-num',
>@keyref, document('serviceManLinkMap.ditamap'))"/>
>        <xsl:variable name="name"
>select="document('serviceManLinkMap.ditamap')/map/keydef/@href"/>
>        <xsl:choose>
>            <xsl:when test="$matching-proc">
>                <child-proc>
>                    <name>
>                        <xsl:value-of select="document($name)/task[@id
>= current()/@keyref]/title"/>
>                    </name>
>                    <frt-num>
>                        <xsl:value-of
>select="$matching-proc/keydef[@keys =
>current()/@keyref]/substring-after(@keys,'X')"/>
>                    </frt-num>
>                </child-proc>
>            </xsl:when>
>            <xsl:otherwise>
>                <child-proc>
>                    <name>
>                        <xsl:text>MISMATCH</xsl:text>
>                    </name>
>                    <frt-num>
>                        <xsl:text>MISMATCH</xsl:text>
>                    </frt-num>
>                </child-proc>
>            </xsl:otherwise>
>        </xsl:choose>
>    </xsl:template>
>
>    <xsl:template match="text()"/>
>
></xsl:stylesheet>
>
>On Mon, Dec 15, 2014 at 4:18 PM, Jason Davis nosaj3@xxxxxxxxx
><xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>> I am currently trying to process multiple files for specific nodes and
>> collect them in a meaningful way to demonstrate the parent-child
>> relationship but I'm having trouble getting past the first level of
>> children.
>>
>> Processor: Saxon PE 9.5.1.7
>> Language version: 2.0
>>
>> A little background:
>>
>> I'm attempting to collect procedure codes from a service manual. The
>> manual is composed of several XMLs. The procedures these codes refer
>> to sometimes refer to subprocedures, which in turn may refer to
>> subprocedures. The link relationship for these subprocedures is
>> managed in a separate map file (also XML).
>>
>> What I want to do is list out all the procedure codes. If there is a
>> subprocedure referenced in a procedure, I want to list its code as a
>> child and continue in this way for all subprocedure until a procedure
>> is listed that does not include a subprocedure.
>>
>> So far, it's really easy for me to:
>>
>>  - process all procedures (aggregated through a file list)
>>  - list the @id (also doubles as the code number) for the procedure
>>  - from a given procedure, process all `xref` nodes found in `cmd`
>> nodes and list the `@keyref` value.
>>
>> The `@keyref` value in an xref is the same as the `@id` of the
>> procedure to which it references. So, in a given procedure, any
>> `cmd/xref/@keyref` value basically refers to a subprocedure. What I am
>> attempting to capture is a list of all the `@id` values for procedures
>> with subprocedures, and in turn, the `@id` of procedures that are
>> subprocedures to subprocedures. I want to do this in a tree that makes
>> the parent/child/descendant relationship clear in terms of what
>> additional procedures someone needs to perform when performing a given
>> procedure.
>>
>> Something like this:
>>
>>     <service-manual>
>>       <procedure>
>>          <name>3 Way Coolant Valve - Chiller Bypass (Remove and
>>Replace)</name>
>>          <frt-num>1234</frt-num>
>>          <child-proc>
>>             <frt-num>10040401</frt-num>
>>             <child-proc>
>>                <frt-num>3456</frt-num>
>>                ...
>>             </child-proc>
>>             <child-proc>
>>                <frt-num>4567</frt-num>
>>                ...
>>             </child-proc>
>>          </child-proc>
>>          <child-proc>
>>             <frt-num>15240701</frt-num>
>>             <child-proc>
>>                <frt-num>1111</frt-num>
>>                ...
>>             </child-proc>
>>             <child-proc>
>>                <frt-num>2222</frt-num>
>>                ...
>>             </child-proc>
>>          </child-proc>
>>          ...
>>       </procedure>
>>        ...
>>
>> What I am having trouble with is figuring out how to process all the
>> procedures an `xref` refers to and list that procedures' children. As
>> previously mentioned, the link relationship is managed through a
>> separate map. What this means is the `@keyref` in an `xref` is bound
>> by a `keydef` element in the map. The keydef element contain two
>> notable attributes: `@keys` which serves as the binding and an `href`
>> that points to a specific resource.
>>
>> What it needs to do is:
>>
>>  - Figure out which `task` to which a given `@keyref` refers.
>>  - List the `@id` of that `task` as a child to the current context.
>>  - Continue processing all the `@keyrefs` in the same way in the
>>decedent chain.
>>
>> The result that I'm getting from my style sheet is only processing the
>> first set of children.
>>
>> Few things about this:
>>
>>  - In all cases, the outermost `task` node is the only relevant `@id`
>> value I'm concerned with. Nested `task` nodes do not factor into this
>> exercise.
>>  - I want to capture all of this in a single XML.
>>  - There are over 500 files referenced in the file list. So, I am just
>> offering a partial sample here.
>>
>> The source XML looks like this:
>>
>>     <?xml version="1.0" encoding="UTF-8"?>
>>     <!DOCTYPE task
>>       PUBLIC "-//OASIS//DTD DITA Task//EN" "task.dtd">
>>     <task id="X1234">
>>        <title>3 Way Coolant Valve - Chiller Bypass (Remove and
>>Replace)</title>
>>        <taskbody>
>>           <prereq>
>>              <p><b>FRT No: 1234</b></p>
>>              <note
>>
>>conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/Jack-Mode-Before-L
>>ifting"/>
>>              <p
>> conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/12v-warnings"/>
>>           </prereq>
>>        </taskbody>
>>        <task id="d1e41176">
>>           <title><ph
>>
>>conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/removal-title"/></
>>title>
>>           <taskbody>
>>              <steps>
>>                 <step>
>>                    <cmd>Some content for the step <xref
>> keyref="X10040401">(refer to procedure)</xref>. </cmd>
>>                 </step>
>>                 <step>
>>                    <cmd><ph
>> conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/disconnect-12v"
>>                       /></cmd>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the steps <xref
>> keyref="X15240701">(refer to
>>                          procedure)</xref>.</cmd>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                    <stepxmp>
>>                       <fig>
>>                          <xref href="repairimages/tss00168.jpg"
>>format="jpg">
>>     <image href="repairthumbs/tss00168.jpg"/>
>>     </xref>
>>                       </fig>
>>                    </stepxmp>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                    <stepxmp>
>>                       <fig>
>>                          <xref href="repairimages/tss00169.jpg"
>>format="jpg">
>>     <image href="repairthumbs/tss00169.jpg"/>
>>     </xref>
>>                       </fig>
>>                    </stepxmp>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                    <stepxmp>
>>                       <fig>
>>                          <xref href="repairimages/tss00170.jpg"
>>format="jpg">
>>     <image href="repairthumbs/tss00170.jpg"/>
>>     </xref>
>>                       </fig>
>>                    </stepxmp>
>>                 </step>
>>              </steps>
>>           </taskbody>
>>        </task>
>>        <task id="d1e41258">
>>           <title><ph
>>
>>conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/installation-title
>>"/></title>
>>           <taskbody>
>>              <steps>
>>                 <step>
>>                    <cmd><ph
>>
>>
>>conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/Install-Reverse-Ex
>>cept"
>>                       /></cmd>
>>                    <info>
>>                       <note
>>
>>conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/Solvents-Ventilate
>>d"/>
>>                       <note
>>
>>conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/Clean-Before-Insta
>>ll"/>
>>                    </info>
>>                 </step>
>>                 <step>
>>                    <cmd>Some content for the step</cmd>
>>                 </step>
>>              </steps>
>>           </taskbody>
>>        </task>
>>     </task>
>>
>> I am using a file list XML as input for processing multiple source
>> files that looks like this:
>>
>>     <directory name="source" size="327680"
>> lastModified="1416254183623" date="20141117T115623"
>> absolutePath="C:\transform_lab\service_manual_projects\frt_work\source"
>> sort="name" reverse="false">
>>        <file name="12V_Positive_Jump_Post_(Remove_and_Replace).xml"
>> size="3690" lastModified="1415930118927" date="20141113T175518"
>>
>>absolutePath="C:\transform_lab\service_manual_projects\frt_work\source\12
>>V_Positive_Jump_Post_(Remove_and_Replace).xml"/>
>>        <file name="200A_Fuses_-_Wall_Connector_(Remove_and_Replace).xml"
>> size="12837" lastModified="1415930118958" date="20141113T175518"
>>
>>absolutePath="C:\transform_lab\service_manual_projects\frt_work\source\20
>>0A_Fuses_-_Wall_Connector_(Remove_and_Replace).xml"/>
>>        <file
>>name="2nd_Row_Center_Console_Assembly_(Remove_and_Replace).xml"
>> size="2552" lastModified="1415930118990" date="20141113T175518"
>>
>>absolutePath="C:\transform_lab\service_manual_projects\frt_work\source\2n
>>d_Row_Center_Console_Assembly_(Remove_and_Replace).xml"/>
>>        <file
>>name="3_Way_Coolant_Valve_-_Chiller_Bypass_(Remove_and_Replace).xml"
>> size="3788" lastModified="1415930119021" date="20141113T175519"
>>
>>absolutePath="C:\transform_lab\service_manual_projects\frt_work\source\3_
>>Way_Coolant_Valve_-_Chiller_Bypass_(Remove_and_Replace).xml"/>
>>        ...
>>     </directory>
>>
>> The key map for this project looks like this:
>>
>>     <map processing-role="resource-only">
>>         <title>Service Manual Link Map</title>
>>         <keydef keys="X1234"
>>
>>href="../section_maps/topics/3_Way_Coolant_Valve_-_Chiller_Bypass_(Remove
>>_and_Replace).xml"/>
>>         ...
>>         <keydef keys="X10040401"
>>
>>href="../section_maps/topics/Raise_Vehicle_-_2_Post_Lift.xml"/>
>>         <keydef keys="X15240701"
>>
>>href="../section_maps/topics/Raise_Vehicle_-_4_Post_Lift.xml"/>
>>         ...
>>     </map>
>>
>>
>> The style sheet I've developed looks like this:
>>
>>     <xsl:template match="/directory">
>>         <service-manual>
>>             <xsl:apply-templates select="file"/>
>>         </service-manual>
>>     </xsl:template>
>>
>>     <xsl:template match="file">
>>         <xsl:variable name="path" select="@name"/>
>>         <xsl:for-each select="document($path)/task">
>>             <procedure>
>>                 <name>
>>                     <xsl:value-of select="title"/>
>>                 </name>
>>                 <frt-num>
>>                     <xsl:value-of select="substring-after(@id,'X')"/>
>>                 </frt-num>
>>                 <xsl:apply-templates/>
>>             </procedure>
>>         </xsl:for-each>
>>     </xsl:template>
>>
>>     <xsl:template match="//cmd/xref">
>>         <xsl:variable name="matching-proc" select="key('proc-num',
>> @keyref, document('serviceManLinkMap.ditamap'))"/>
>>         <xsl:variable name="name"
>> select="document('serviceManLinkMap.ditamap')/map/keydef/@href"/>
>>         <xsl:choose>
>>             <xsl:when test="$matching-proc">
>>                 <child-proc>
>>                     <name>
>>                         <xsl:value-of select="document($name)/task[@id
>> = current()/@keyref]/title"/>
>>                     </name>
>>                     <frt-num>
>>                         <xsl:value-of
>> select="$matching-proc/keydef[@keys =
>> current()/@keyref]/substring-after(@keys,'X')"/>
>>                     </frt-num>
>>                 </child-proc>
>>             </xsl:when>
>>             <xsl:otherwise>
>>                 <child-proc>
>>                     <name>
>>                         <xsl:text>MISMATCH</xsl:text>
>>                     </name>
>>                     <frt-num>
>>                         <xsl:text>MISMATCH</xsl:text>
>>                     </frt-num>
>>                 </child-proc>
>>             </xsl:otherwise>
>>         </xsl:choose>
>>     </xsl:template>
>>
>>     <xsl:template match="text()"/>
>>
>> This only gets me part of the way. With this, I'm able to process all
>> the procedures that correlate to the value of `file` and process the
>> `xrefs` of that procedure to find its subprocedures. However, I have
>> not been able to figure out how to do the same with the subprocedures
>> of a subprocedure.
>>
>> And believe me, I'm sure there are better ways to accomplish what I am
>> attempting. So, any insights or suggestions for improvement, better
>> efficiency, etc. are greatly appreciated. I'm pretty much an amateur
>> with XSLT. So, please let me know if I am missing anything.
>>
>> Thanks,
>> Jason

Current Thread