XSLT - 获取结果树的原始属性

时间:2015-09-18 16:52:00

标签: xml xslt xslt-2.0

我有像这样的xml,

<doc>
    <section type="Main_Content">
        <p id="main">aa</p>
        <p id="main">bb</p>
        <p id="main">cc</p>
        <p id="para1">dd</p>
        <p id="main">ee</p>
        <p id="main">ff</p>
        <p id="para2">hh</p>
        <p id="main">ii</p>
        <p id="main">jj</p>
        <p id="para1">xx</p>
        <p id="main">yy</p>

    </section>
    <section type="Main_Chapter">
        <p id="main">ii</p>
        <p id="main">jj</p>
        <p id="para1">xx</p>
        <p id="main">yy</p>
        <p id="main">zz</p>    
    </section>
</doc>

我的任务是基于id =“para1”和id ='para2'属性对上述内容进行分组,并为每个组添加一个部分。我想要的输出是

<doc>
    <section type="Main_Content">
        <p id="main">aa</p>
        <p id="main">bb</p>
        <p id="main">cc</p>
    </section>
    <section type="First para">
        <p id="para1">dd</p>
        <p id="main">ee</p>
        <p id="main">ff</p>
    </section>
    <section type="Second para">
        <p id="para2">hh</p>
        <p id="main">ii</p>
        <p id="main">jj</p>
    </section>
    <section type="First para">
        <p id="para1">xx</p>
        <p id="main">yy</p>
    </section>
    <section type="Main_Chapter">
        <p id="main">ii</p>
        <p id="main">jj</p>
    </section>
    <section type="First para">
        <p id="para1">xx</p>
        <p id="main">yy</p>
        <p id="main">zz</p>
    </section>
</doc>

此任务的XSL代码是

<xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="section">
        <xsl:for-each-group select="p" group-starting-with="p[starts-with(@id, 'para')]">
            <section type="{@type}">
                <xsl:if test="current-group()[1][@id='para1']">
                    <xsl:attribute name="type" select="'First para'"/>
                </xsl:if>
                <xsl:if test="current-group()[1][@id='para2']">
                    <xsl:attribute name="type" select="'Second para'"/>
                </xsl:if>
                <xsl:apply-templates select="current-group()"/>
            </section>      
        </xsl:for-each-group>
    </xsl:template>

从xsl以上获取的结果是,

<doc>
    <section type="">
        <p id="main">aa</p>
        <p id="main">bb</p>
        <p id="main">cc</p>
    </section>
    <section type="First para">
        <p id="para1">dd</p>
        <p id="main">ee</p>
        <p id="main">ff</p>
    </section>
    <section type="Second para">
        <p id="para2">hh</p>
        <p id="main">ii</p>
        <p id="main">jj</p>
    </section>
    <section type="First para">
        <p id="para1">xx</p>
        <p id="main">yy</p>
    </section>
    <section type="">
        <p id="main">ii</p>
        <p id="main">jj</p>
    </section>
    <section type="First para">
        <p id="para1">xx</p>
        <p id="main">yy</p>
        <p id="main">zz</p>
    </section>
</doc>

因此,除了原始type属性未复制到<section>节点外,结果外观似乎是正确的。如何修改xsl以将原始type属性值提供给<section>个节点?

1 个答案:

答案 0 :(得分:4)

问题在于提供的代码的这一部分:

<xsl:template match="section">
    <xsl:for-each-group select="p" group-starting-with="p[starts-with(@id, 'para')]">
        <section type="{@type}">

请注意,context(current)项是p元素,并且提供的源XML文档中没有这些元素具有type属性。

在此您需要type元素的父级的p属性。

<强>解决方案

替换:

        <section type="{@type}">

使用:

        <section type="{../@type}">

现在整个转型变为

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

 <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
 </xsl:template>

 <xsl:template match="section">
   <xsl:for-each-group select="p"  group-starting-with="p[starts-with(@id, 'para')]">
      <section type="{../@type}">
        <xsl:if test="current-group()[1][@id='para1']">
           <xsl:attribute name="type" select="'First para'"/>
         </xsl:if>
         <xsl:if test="current-group()[1][@id='para2']">
            <xsl:attribute name="type" select="'Second para'"/>
          </xsl:if>
          <xsl:apply-templates select="current-group()"/>
      </section>      
   </xsl:for-each-group>
 </xsl:template>
</xsl:stylesheet>

并应用于提供的源XML文档

<doc>
    <section type="Main_Content">
        <p id="main">aa</p>
        <p id="main">bb</p>
        <p id="main">cc</p>
        <p id="para1">dd</p>
        <p id="main">ee</p>
        <p id="main">ff</p>
        <p id="para2">hh</p>
        <p id="main">ii</p>
        <p id="main">jj</p>
        <p id="para1">xx</p>
        <p id="main">yy</p>
    </section>
    <section type="Main_Chapter">
        <p id="main">ii</p>
        <p id="main">jj</p>
        <p id="para1">xx</p>
        <p id="main">yy</p>
        <p id="main">zz</p>
    </section>
</doc>

产生了想要的正确结果:

<doc>
   <section type="Main_Content">
      <p id="main">aa</p>
      <p id="main">bb</p>
      <p id="main">cc</p>
   </section>
   <section type="First para">
      <p id="para1">dd</p>
      <p id="main">ee</p>
      <p id="main">ff</p>
   </section>
   <section type="Second para">
      <p id="para2">hh</p>
      <p id="main">ii</p>
      <p id="main">jj</p>
   </section>
   <section type="First para">
      <p id="para1">xx</p>
      <p id="main">yy</p>
   </section>
      <section type="Main_Chapter">
      <p id="main">ii</p>
      <p id="main">jj</p>
   </section>
   <section type="First para">
      <p id="para1">xx</p>
      <p id="main">yy</p>
      <p id="main">zz</p>
   </section>
</doc>