如何在XSLT中使用多个文件作为输入,以与父节点相同的方式处理子节点?

时间:2014-12-09 18:22:16

标签: xml xslt

我目前正在尝试为特定节点处理多个文件,并以有意义的方式收集这些文件以展示父子关系,但是我无法越过第一级别的孩子。

一点背景:

我试图从服务手册中收集程序代码。该手册由几个XML组成。这些代码所涉及的过程有时指的是子过程,而子过程又可以指子过程。我想列出所有程序代码。如果在过程中引用了子过程,我想将其代码列为子项,并以这种方式继续所有子过程,直到列出的过程不包含子过程。

到目前为止,我真的很容易:

  • 处理所有程序(包含在文件列表中)
  • 列出程序的frt编号
  • 来自给定过程的
  • 处理xref个节点中找到的所有cmd个节点,并列出@keyref值。

@keyref值与它引用的过程的@id相同。因此,在给定的过程中,任何cmd/xref/@keyref值基本上都是指子过程。我试图捕获的是包含子过程的过程的所有@id值的列表,反过来,是子过程子过程的@id过程的列表。我想在树中执行此操作,使父/子/后代关系在执行给定过程时需要执行的其他过程方面明确。

这样的事情:

<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>
...

我遇到的问题是如何处理xref引用的所有程序并列出其子项。它需要做的是:

  • 找出给定task所指的@keyref
  • @id的{​​{1}}列为当前上下文的子项。
  • 继续在死亡链中以相同的方式处理所有task

我从样式表中获得的结果只是处理第一组孩子。

关于这一点很少:

  • 在所有情况下,最外面的@keyrefs节点是我唯一关注的task值。嵌套的@id节点不会参与此练习。
  • 我想在一个XML中捕获所有这些内容。
  • 文件列表中引用了500多个文件。所以,我只是在这里提供部分样本。

源XML看起来像这样:

task

我使用文件列表XML作为输入来处理多个源文件,如下所示:

<?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>

我开发的样式表看起来像这样:

<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>
显然,这是错误的。我的想法是我应该创建一个处理外部参照节点的模板,然后从// cmd模板中调用该模板但是效果不是很好。这是我应该采取的方向吗?此外,这里使用模式选项吗?由于我有点像业余爱好者,成功实现这一目标的逻辑让我的大脑扭曲了一下。任何帮助表示赞赏。

我想到的一种方法,但不确定如何开展工作是使用<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)/*"> <xsl:for-each select="/*"> <procedure> <name> <xsl:value-of select="title"/> </name> <frt-num> <xsl:value-of select="substring-after(@id,'X')"/> </frt-num> <xsl:apply-templates select="//cmd"/> </procedure> </xsl:for-each> </xsl:for-each> </xsl:template> <xsl:template match="//cmd"> <xsl:for-each select="xref"> <child-proc> <frt-num> <xsl:value-of select="substring-after(@keyref,'X')"/> </frt-num> <xsl:apply-templates select="file"/> </child-proc> </xsl:for-each> </xsl:template> 在用于管理链接资源的键映射中进行查找。 key()的值映射到@keyref元素上@keya属性的值。所有keydef元素都收集在与服务手册内容分开的地图中。该项目的关键地图如下所示:

keydef

现在我想到了,我提出的任何解决方案都必须在键映射中包含查找,因为这是确定给定<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> 映射的任务的唯一方法。

1 个答案:

答案 0 :(得分:0)

许多事情仍然不清楚,但您可能更容易对尝试的解决方案发表评论。让我知道我还不太了解的内容。

我已使用您的输入XML,但我已对目录文件进行了更改。它现在只包含一个文件引用(因为我只有你显示的那个):

<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"/>
</directory>

<强>样式表

你可以取消大多数xsl:for-each构造,其中一些只是多余的,其他的最好用模板替换。

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">

    <xsl:output method="xml" indent="yes"/>

    <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="xref|task/task">
            <child-proc>
                <frt-num>
                    <xsl:value-of select="substring-after(@keyref,'X')"/>
                </frt-num>                
                <xsl:apply-templates/>
            </child-proc>            
    </xsl:template>

    <xsl:template match="text()"/>

</xsl:stylesheet>

XML输出

如您所见,某些frt-num元素为空,因为某些xref元素没有@keyref属性。在这种情况下,我怀疑,他们没有引用另一个子进程。

<?xml version="1.0" encoding="UTF-8"?>
<service-manual>
   <procedure>
      <name>3 Way Coolant Valve - Chiller Bypass (Remove and Replace)</name>
      <frt-num>1234</frt-num>
      <child-proc>
         <frt-num/>
         <child-proc>
            <frt-num>10040401</frt-num>
         </child-proc>
         <child-proc>
            <frt-num>15240701</frt-num>
         </child-proc>
         <child-proc>
            <frt-num/>
         </child-proc>
         <child-proc>
            <frt-num/>
         </child-proc>
         <child-proc>
            <frt-num/>
         </child-proc>
      </child-proc>
      <child-proc>
         <frt-num/>
         <child-proc>
            <frt-num>46010000</frt-num>
         </child-proc>
      </child-proc>
   </procedure>
</service-manual>
相关问题