[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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


Subject: [xsl] Want to process child and decendent nodes the same way as parent node but can only process children
From: "Jason Davis nosaj3@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Tue, 16 Dec 2014 00:18:04 -0000

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-Lifting"/>
             <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-Except"
                      /></cmd>
                   <info>
                      <note
conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/Solvents-Ventilated"/>
                      <note
conref="../../resources/SM-reuse.dita#topic_nsx_hq3_sl/Clean-Before-Install"/>
                   </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\12V_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\200A_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\2nd_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
Keywords
xml