XSLT 2.0-使用分组嵌套元素 [英] XSLT 2.0 - Using Grouping To Nest Elements

查看:70
本文介绍了XSLT 2.0-使用分组嵌套元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理一个样式表,该样式表从输入文件中以几乎没有格式输出分层格式。每个部分的层次结构极其扁平,因此我一直在使用一种建议给我的分组方法-它按第一个节点名称对每个集合进行分组,从而使平坦部分具有很好的层次结构。此方法效果很好-我只需要修改它即可解决我想跳过的元素。

I'm working on a stylesheet that outputs in a hierarchical format from an input file with almost none. Each section has an extremely flat hierarchy, so I've been using a grouping method that was suggested to me - it groups each set by the first node name, and thus makes a nice heirarchy out of flat sections. This method works great - I just need to modify it to account for elements I want to skip over.

示例输入文件(注意:每个节中有多个Header元素) :

Sample input file (note: there are multiple Header elements per Section):

<Root>
    <VolumeName>Volume 1 </VolumeName>
    <Section>
        <SectionName> Section1 </SectionName>
        <Title> Title1 </Title>
        <Header> NameOfDocument1 </Header>
        <Header> Header1 </Header> 
        <Sub1> Sub1 first </Sub1> 
        <Sub1> Sub1 second </Sub1>
        <Sub2> Sub2 first, Sub1 second </Sub2> 
        <Sub1> Sub1 third </Sub1> 
        <Sub2> Sub2 first, Sub1 third </Sub2>
    </Section>

    <Section>
        <SectionName> Section2 </SectionName>
        <Title> Title2 </Title>
        <Header> Header2 </Header> 
        <Sub1> Sub1 first </Sub1> 
        <Sub1> Sub1 second </Sub1>
        <Sub2> Sub2 first, Sub1 second </Sub2> 
        <Sub1> Sub1 third </Sub1> 
        <Sub2> Sub2 first, Sub1 third </Sub2>
    </Section>
</Root>

示例输入代码的输出应类似于:

The output of the sample input code should look like:

<Volume1>
    <Section1 Number="Section1" Name="NameOfDocument1" Title="Title1">
        <Header1>
            <Step>
                Sub1 first
            </Step>
            <Step>
                Sub1 second
                <Step>
                    Sub2 first, Sub1 second
                </Step>
            </Step>
            <Step>
                Sub1 third
                <Step>
                    Sub2 first, Sub1 third
                </Step>
             </Step> 
        </Header1>
    </Section1>

    <Section2 Number="Section2" Name="concat('NameOfDocument','2')" Title="Title2">
            <Step>
                Sub1 first
            </Step>
            <Step>
                Sub1 second
                <Step>
                    Sub2 first, Sub1 second
                </Step>
            </Step>
            <Step>
                Sub1 third
                <Step>
                    Sub2 first, Sub1 third
                </Step>
             </Step> 
    </Section2>
</Volume1>

感谢Dimitrie Novatchev,我现在有一些代码可以处理Section元素内的扁平部分。我有一个与Section元素匹配的模板,然后声明了一个元素,并从SectionName,Title和Header中获取信息,以填写该元素的名称及其属性。我想跳过SectionName,Title,有时甚至是Header,但不确定如何修改Dimitrie的代码。任何建议将不胜感激!谢谢!

Thanks to Dimitrie Novatchev, I now have some code that will handle the flat parts inside the Section elements. I have a template match for the Section element, then I declare an element and grab information from SectionName, Title, and sometimes Header to fill in what the element will be called and its attributes. I want to skip SectionName, Title, and sometimes Header and I'm not sure how to modify Dimitrie's code to do so. Any suggestions would be greatly appreciated! Thank you!

Dimitrie的分组代码:

Dimitrie's grouping code:

<xsl:stylesheet version="2.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:template match="/*">
        <Root>
            <xsl:apply-templates select="*[1]">
                <xsl:with-param name="pScope" select="*"/>
                <xsl:with-param name="pElemName" select="name(*[1])"/>
            </xsl:apply-templates>
         </Root>
    </xsl:template>

   <xsl:template match="*">
       <xsl:param name="pScope"/>
       <xsl:param name="pElemName" select="'Step'"/>
       <xsl:for-each-group select="$pScope" 
            group-starting-with="*[name()= name($pScope[1])]">
           <xsl:element name="{$pElemName}">
               <xsl:value-of select="."/>
               <xsl:apply-templates select="current-group()[2]">
                   <xsl:with-param name="pScope" 
                       select="current-group()[position() > 1]"/>
               </xsl:apply-templates>
           </xsl:element>
       </xsl:for-each-group>
   </xsl:template>
</xsl:stylesheet>


推荐答案

以下是我的答案的改编或产生现在想要的结果的最初问题:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
  <Root>
   <xsl:element name="{translate(VolumeName,' ','')}">
    <xsl:apply-templates/>
   </xsl:element>
  </Root>
 </xsl:template>

 <xsl:template match="*">
  <xsl:param name="pScope"/>
  <xsl:param name="pElemName" select="'Step'"/>
  <xsl:for-each-group select="$pScope"
        group-starting-with=
        "*[name()= name($pScope[1])]">
   <xsl:element name="{$pElemName}">
    <xsl:value-of select="."/>
    <xsl:apply-templates select="current-group()[2]">
     <xsl:with-param name="pScope"
          select="current-group()[position() > 1]"/>
    </xsl:apply-templates>
   </xsl:element>
  </xsl:for-each-group>
 </xsl:template>

 <xsl:template match="VolumeName"/>

 <xsl:template match="Section">
  <xsl:element name=
      "{normalize-space(SectionName)}">
   <xsl:attribute name="Number"
        select="normalize-space(SectionName)"/>
   <xsl:attribute name="Name" select=
   "concat('NameOfDocument',
           count(preceding-sibling::Section)+1)"/>
   <xsl:attribute name="Title"
       select="normalize-space(Title)"/>"

   <xsl:variable name="vOutput">
    <xsl:apply-templates select="*[1]">
     <xsl:with-param name="pScope"
        select="Header[last()]/following-sibling::*"/>
     <xsl:with-param name="pElemName" select=
      "(normalize-space(Header[2]), 'Step')[last()]"/>
    </xsl:apply-templates>
   </xsl:variable>

   <xsl:choose>
    <xsl:when test="Header[2]">
     <xsl:element name="{normalize-space(Header[2])}">
      <xsl:sequence select="$vOutput"/>
     </xsl:element>
    </xsl:when>
    <xsl:otherwise>
      <xsl:sequence select="$vOutput"/>
    </xsl:otherwise>
   </xsl:choose>
  </xsl:element>
 </xsl:template>
 </xsl:stylesheet>

当此转换应用于提供的XML文档时:

<Root>
    <VolumeName>Volume 1 </VolumeName>
    <Section>
        <SectionName> Section1 </SectionName>
        <Title> Title1 </Title>
        <Header> NameOfDocument1 </Header>
        <Header> Header1 </Header>
        <Sub1> Sub1 first </Sub1>
        <Sub1> Sub1 second </Sub1>
        <Sub2> Sub2 first, Sub1 second </Sub2>
        <Sub1> Sub1 third </Sub1>
        <Sub2> Sub2 first, Sub1 third </Sub2>
    </Section>
    <Section>
        <SectionName> Section2 </SectionName>
        <Title> Title2 </Title>
        <Header> Header2 </Header>
        <Sub1> Sub1 first </Sub1>
        <Sub1> Sub1 second </Sub1>
        <Sub2> Sub2 first, Sub1 second </Sub2>
        <Sub1> Sub1 third </Sub1>
        <Sub2> Sub2 first, Sub1 third </Sub2>
    </Section>
</Root>

产生了所需的结果:

<Root>
    <Volume1>
        <Section1 Number="Section1" Name="NameOfDocument1" Title="Title1">"

            <Header1>
                <Step> Sub1 first </Step>
                <Step> Sub1 second 
                    <Step> Sub2 first, Sub1 second </Step></Step>
                <Step> Sub1 third 
                    <Step> Sub2 first, Sub1 third </Step></Step>
            </Header1>
        </Section1>
        <Section2 Number="Section2" Name="NameOfDocument2" Title="Title2">"

            <Step> Sub1 first </Step>
            <Step> Sub1 second 
                <Step> Sub2 first, Sub1 second </Step></Step>
            <Step> Sub1 third 
                <Step> Sub2 first, Sub1 third </Step></Step>
        </Section2>
    </Volume1>
</Root>

这篇关于XSLT 2.0-使用分组嵌套元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆