【问题标题】:Three-level Group using XSLT使用 XSLT 的三级组
【发布时间】:2013-02-04 05:29:47
【问题描述】:

我有一个 XML 文件,其中列出了学位课程下的课程。我创建了一个 XSLT(在帮助下),它成功地在学位名称下创建了类组。但是客户想要一个识别选修课和非选修课的第三级。如果是选修课,选修课将与数据“Y”一起列出,如果不是选修课,则与“N”一起列出,否则为“程序要求”。

如果元素<FlagElectives1> 中有“N”,我需要向 XSLT 添加另一个级别,该级别将类分组到标题“程序要求”下。

我想我需要根据这个元素创建另一个键,对,然后创建一个模板来创建一个 xsl:text 标题,上面写着:“程序要求”或“程序选修”,但我被卡住了。我以前从未做过三级分组。

这是我的 XSLT:

<?xml version="1.0"?>
<!-- DWXMLSource="STX049 Catalog parsed.xml" -->
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no"/>
  <xsl:template match="/">

    <CrystalReport>
      <xsl:apply-templates/>
    </CrystalReport>
  </xsl:template>


  <xsl:key name="degrees-by-title" match="CrystalReport/Group/Group/Group/Details" use="Section/ICCB1" />

  <xsl:template match="CrystalReport/Group/Group/Group">

    <Degree>
      <xsl:for-each select="Details[count(. | key('degrees-by-title', Section/ICCB1)[1]) = 1]">
        <xsl:sort select="Section/ACADPROGRAMSID1" />
        <department>
          <Degreetitle>
            <xsl:apply-templates select="Section/ACPGDEGREE1" />
          </Degreetitle>
          <Certtitle>
            <xsl:apply-templates select="Section/CCD11" />
          </Certtitle>
          <DegreeDesc>
            <xsl:value-of select="Section/ACPGCOMMENTS1"/>
          </DegreeDesc>
          <ICCBcode>
            <xsl:value-of select="Section/ICCB1"/>
          </ICCBcode>
          <ProgramID>
            <xsl:value-of select="Section/ACADPROGRAMSID1"/>
          </ProgramID>
          <xsl:for-each select="key('degrees-by-title', Section/ICCB1)">
            <xsl:sort select="Section/FlagElectives1" order="ascending" />
            <xsl:sort select="Section/DEPARTMENT11" />
            <xsl:sort select="Section/CRSNO1" />

            <Details>
              <class>
                <deptname>
                  <xsl:value-of select="Section/DEPARTMENT11"/>
                </deptname>
                <courseno>
                  <xsl:value-of select="Section/CRSNO1"/>
                </courseno>
                <classname>
                  <xsl:value-of select="Section/CRSTITLE1"/>
                </classname>
                <classcredit>
                  <xsl:value-of select="Section/CRSMINCRED1"/>
                </classcredit>
                <Elective>
                  <xsl:value-of select="Section/FlagElectives1" />
                </Elective>
              </class>
            </Details>

          </xsl:for-each>
        </department>
      </xsl:for-each>
    </Degree>

  </xsl:template>

  <xsl:template match="Section/ACPGDEGREE1[child::node()]">
    <xsl:value-of select="."/>
    <xsl:text> DEGREE</xsl:text>
  </xsl:template>

  <xsl:template match="Section/CCD11[child::node()]">
    <xsl:text> CERTIFICATE</xsl:text>
  </xsl:template>


</xsl:stylesheet>

这是我的 XML 的结构:

<?xml version="1.0" encoding="UTF-8"?>
<CrystalReport>
  <Group Level="1">
    <Group Level="2">
      <Group Level="3">
        <Details>
          <Section>
            <ACPGDEGREE1>AAS</ACPGDEGREE1>
            <CCD11/>
            <ACPGCOMMENTS1>The Accounting program</ACPGCOMMENTS1>
            <ICCB1>3203</ICCB1>
            <ACADPROGRAMSID1>ACCOU.AAS</ACADPROGRAMSID1>
            <CRSNO1>1110</CRSNO1>
            <ACRBPRINTEDSPEC1/>
            <ACPGHOMELANGNOTREQDRSN1>General Education</ACPGHOMELANGNOTREQDRSN1>
            <CRSMINCRED1>2</CRSMINCRED1>
            <ACPGAREAOFSTUDY1>Accounting</ACPGAREAOFSTUDY1>
            <CRSTITLE1>Using Computers: An Introduction</CRSTITLE1>
            <DEPARTMENT11>ACCOU</DEPARTMENT11>
            <CRSSUBJECT1>CIS</CRSSUBJECT1>
            <ACRBLABEL1>CIS REQUIREMENT</ACRBLABEL1>
            <CRSMAXCRED1/>
            <FlagElectives1>N</FlagElectives1>
          </Section>
        </Details>
        <Details>
          <Section>
            <ACPGDEGREE1>AAS</ACPGDEGREE1>
            <CCD11/>
            <ACPGCOMMENTS1>The Accounting program</ACPGCOMMENTS1>
            <ICCB1>3203</ICCB1>
            <ACADPROGRAMSID1>ACCOU.AAS</ACADPROGRAMSID1>
            <CRSNO1>1150</CRSNO1>
            <ACRBPRINTEDSPEC1/>
            <ACPGHOMELANGNOTREQDRSN1>General Education</ACPGHOMELANGNOTREQDRSN1>
            <CRSMINCRED1>3</CRSMINCRED1>
            <ACPGAREAOFSTUDY1>Accounting</ACPGAREAOFSTUDY1>
            <CRSTITLE1>Intro to Computer</CRSTITLE1>
            <DEPARTMENT11>ACCOU</DEPARTMENT11>
            <CRSSUBJECT1>CIS</CRSSUBJECT1>
            <ACRBLABEL1>CIS</ACRBLABEL1>
            <CRSMAXCRED1/>
            <FlagElectives1>Y</FlagElectives1>
          </Section>
        </Details>
      </Group>
    </Group>
  </Group>
</CrystalReport>

第一级分组应该基于元素&lt;DEPARTMENT11&gt;。在&lt;ACPGAREAOFSTUDY1&gt;字段中可以找到各种学位和证书的名称 所有这一切中的第二级唯一字段是&lt;ACADPROGRAMSID1&gt;

这是所需的输出:

<CrystalReport>
 <Degrees>

 <!--group and repeat "Degrees" for-each based on element ACPGAREAOFSTUDY1-->

 <areaofstudy>Accounting</areaofstudy>
 <Degree>
 <department>

 <!--group and repeat "department" for-each based on element ICCB1-->

  <Degreetitle>AAS DEGREE</Degreetitle>
  <Certtitle />
  <DegreeDesc>The Accounting program</DegreeDesc>
  <ICCBcode>3203</ICCBcode>
  <ProgramID>ACCOU.AAS</ProgramID>

 <!--group and repeat "Details" for-each based on element ACADPROGRAMSID1 under titles "Program Requirement" or "Program Elective" based on element "FlagElectives1"-->

  <h1>Program Requirements</h1>
  <Details>
    <class>
      <deptname>ACCOU</deptname>
      <courseno>1150</courseno>
      <classname>Intro to Computer</classname>
      <classcredit>3</classcredit>
      <Elective>N</Elective>
    </class>
  </Details>
  <h1>Program Electives</h1>
  <Details>
    <class>
      <deptname>ACCOU</deptname>
      <courseno>1110</courseno>
      <classname>Using Computers: An Introduction</classname>
      <classcredit>2</classcredit>
      <Elective>Y</Elective>
    </class>
  </Details>
 </department>
 </Degree>
 <Degree>
 <department>
  <Degreetitle>AAS DEGREE</Degreetitle>
  <Certtitle />
  <DegreeDesc>The Accounting program</DegreeDesc>
  <ICCBcode>3203</ICCBcode>
  <ProgramID>ACCOU.AAS</ProgramID>
  <h1>Program Requirements</h1>
  <Details>
    <class>
      <deptname>ACCOU</deptname>
      <courseno>1150</courseno>
      <classname>Intro to Computer</classname>
      <classcredit>3</classcredit>
      <Elective>Y</Elective>
    </class>
  </Details>
  <h1>Program Electives</h1>
  <Details>
    <class>
      <deptname>ACCOU</deptname>
      <courseno>1110</courseno>
      <classname>Using Computers: An Introduction</classname>
      <classcredit>2</classcredit>
      <Elective>N</Elective>
    </class>
  </Details>
</department>
</Degree>
</Degrees>
</CrystalReport>

【问题讨论】:

  • 您能给我们举个例子说明您希望输出的样子吗?
  • 我看到您为后续问题打开了一个单独的问题。我在此处或在我回答的其他问题(关于名称空间)中的回答对您有帮助吗?如果是这样,您能否将它们标记为答案?
  • 您是否更新了另一个问题的相同代码的答案?如果您这样做,我会将其标记为答案。我打开了第二个问题,因为有些人不允许问题中有多个步骤。一个问题 -> 一个答案。但更新后的 XSLT 更接近最终解决方案。
  • 现在更新了,是的,我认为打开新问题而不是让一个原始问题拖出许多新要求是个好主意。

标签: xml xslt


【解决方案1】:

我对您的 XSLT 做了一些清理工作。任何时候你有一个for-each 嵌套在一个for-each 中,这是一个很好的迹象,表明你的XSLT 需要一些重构。我想我已经理解了你的意思,通过课程是否是选修课来分组(尽管你没有说明你想如何表示),所以我想出了以下内容:

<?xml version="1.0"?>
<!-- DWXMLSource="STX049 Catalog parsed.xml" -->
<!DOCTYPE xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="no"/>
  <xsl:variable name="allSections" 
                select="/CrystalReport/Group/Group/Group/Details/Section" />

  <xsl:key name="kArea" match="Section" use="ACPGAREAOFSTUDY1"/>
  <xsl:key name="kDegree" match="Section" 
           use="concat(ACPGAREAOFSTUDY1, '+', ACPGDEGREE1)" />
  <xsl:key name="kDepartment" match="Section" 
           use="concat(ACPGAREAOFSTUDY1, '+', ACPGDEGREE1, '+', ICCB1)" />

  <xsl:variable name="degreeFirsts"
           select="$allSections[generate-id() = 
             generate-id(key('kDegree', 
                concat(ACPGAREAOFSTUDY1, '+', ACPGDEGREE1))[1])]" />
  <xsl:variable name="deptFirsts"
             select="$allSections[generate-id() = 
               generate-id(key('kDepartment',
                concat(ACPGAREAOFSTUDY1, '+', ACPGDEGREE1, '+', ICCB1))[1])]" />


  <xsl:template match="/">
    <CrystalReport>
      <Degrees>
        <xsl:apply-templates
          select="$allSections[generate-id() = 
                 generate-id(key('kArea', ACPGAREAOFSTUDY1)[1])]"
          mode="group"/>
      </Degrees>
    </CrystalReport>
  </xsl:template>

  <xsl:template match="Section" mode="group">
    <xsl:variable name="area" select="ACPGAREAOFSTUDY1" />
    <areaofstudy>
      <xsl:value-of select="$area"/>
    </areaofstudy>
    <xsl:apply-templates select="$degreeFirsts[ACPGAREAOFSTUDY1 = $area]" 
                         mode="degree"/>
  </xsl:template>

  <xsl:template match="Section" mode="degree">
    <xsl:variable name="area" select="ACPGAREAOFSTUDY1" />
    <xsl:variable name="degree" select="ACPGDEGREE1" />
    <xsl:text>&#xA;</xsl:text>
    <Degree>
      <xsl:apply-templates
        select="$deptFirsts[ACPGAREAOFSTUDY1 = $area and ACPGDEGREE1 = $degree]"
        mode="department">
        <xsl:sort select="ACADPROGRAMSID1" />
      </xsl:apply-templates>
    </Degree>
  </xsl:template>

  <xsl:template match="Section" mode="department">
    <department>
      <Degreetitle>
        <xsl:apply-templates select="ACPGDEGREE1" />
      </Degreetitle>
      <Certtitle>
        <xsl:apply-templates select="CCD11" />
      </Certtitle>
      <xsl:text>&#xA;</xsl:text>
      <DegreeDesc>
        <xsl:apply-templates select="ACPGCOMMENTS1" />
      </DegreeDesc>
      <xsl:text>&#xA;ICCB Code</xsl:text>
      <ICCBcode>
        <xsl:apply-templates select="ICCB1" />
      </ICCBcode>
      <xsl:text> | Field of Study Code: </xsl:text>
      <ProgramID>
        <xsl:apply-templates select="ACADPROGRAMSID1" />
      </ProgramID>
      <xsl:variable name="courses" 
              select="key('kDepartment', 
                   concat(ACPGAREAOFSTUDY1, '+', ACPGDEGREE1, '+', ICCB1))" />

      <xsl:call-template name="CourseGroup">
        <xsl:with-param name="courses" select="$courses[FlagElectives1 = 'N']" />
        <xsl:with-param name="title" select="'Program Requirements'" />
      </xsl:call-template>

      <xsl:call-template name="CourseGroup">
        <xsl:with-param name="courses" select="$courses[FlagElectives1 = 'Y']" />
        <xsl:with-param name="title" select="'Program Electives'" />
      </xsl:call-template>
    </department>
  </xsl:template>

  <xsl:template name="CourseGroup">
    <xsl:param name="courses" />
    <xsl:param name="title" />

    <xsl:if test="$courses">
      <xsl:text>&#xA;</xsl:text>
      <xsl:value-of select="$title" />
      <xsl:apply-templates select="$courses">
        <xsl:sort select="FlagElectives1" order="ascending" />
        <xsl:sort select="DEPARTMENT11" />
        <xsl:sort select="CRSNO1" />
      </xsl:apply-templates>
    </xsl:if>
  </xsl:template>

  <xsl:template match="Section">
    <xsl:text>&#xA;</xsl:text>
    <Details>
      <class>
        <deptname>
          <xsl:apply-templates select="DEPARTMENT11" />
        </deptname>
        <xsl:text>    </xsl:text>
        <courseno>
          <xsl:apply-templates select="CRSNO1" />
        </courseno>
        <xsl:text>   </xsl:text>
        <classname>
          <xsl:apply-templates select="CRSTITLE1" />
        </classname>
        <xsl:text>    </xsl:text>
        <classcredit>
          <xsl:apply-templates select="CRSMINCRED1" />
        </classcredit>
      </class>
    </Details>
  </xsl:template>

  <xsl:template match="ACPGDEGREE1/text()">
    <xsl:value-of select="concat(., ' DEGREE')"/>
  </xsl:template>

  <xsl:template match="CCD11/text()">
    <xsl:value-of select="concat(., ' CERTIFICATE')" />
  </xsl:template>
</xsl:stylesheet>

选修分组是通过call-template项来实现的,根据是否选修来选择课程:

  <xsl:variable name="courses" 
                select="key('degrees-by-title', ICCB1)" />
  <xsl:call-template name="CourseGroup">
    <xsl:with-param name="courses" select="$courses[FlagElectives1 = 'Y']" />
    <xsl:with-param name="title" select="'Program Requirements'" />
  </xsl:call-template>

在您的示例输入上运行时,此 XSLT 会生成:

<CrystalReport>
  <Degree>
    <department>
      <Degreetitle>AAS DEGREE</Degreetitle>
      <Certtitle />
      <DegreeDesc>The Accounting program</DegreeDesc>
      <ICCBcode>3203</ICCBcode>
      <ProgramID>ACCOU.AAS</ProgramID>
      <h1>Program Requirements</h1>
      <Details>
        <class>
          <deptname>ACCOU</deptname>
          <courseno>1150</courseno>
          <classname>Intro to Computer</classname>
          <classcredit>3</classcredit>
          <Elective>Y</Elective>
        </class>
      </Details>
      <h1>Program Electives</h1>
      <Details>
        <class>
          <deptname>ACCOU</deptname>
          <courseno>1110</courseno>
          <classname>Using Computers: An Introduction</classname>
          <classcredit>2</classcredit>
          <Elective>N</Elective>
        </class>
      </Details>
    </department>
  </Degree>
</CrystalReport>

注意h1 元素,注意要求和选修组的开始。如果您希望它以其他方式表示,请澄清这一点。

【讨论】:

  • 对不起,我现在完全糊涂了。我以前从未使用过这种方法。使用这个样式表,我丢失了所有现有的标记名。您的样式表为我提供了数据,但没有返回许多项目的标签。当我在数据上运行它时,我得到 ACCOU2200Income Tax Return Preparation3Y 而不是:ACCOU2200Income Tax Return Preparation 3Y 如何恢复结果中的标记名?我还想使用一些 元素。我要构建更多模板吗?
  • 您是在输入中使用我所有的 XSLT,还是只使用其中的一部分?我通过查找旧元素名称-> 新元素名称进行了修改以使 XSLT 更简洁,但这使用了document() 函数,并且您的 XSLT 处理器可能对该函数有限制。你能告诉我你用的是什么处理器吗?
  • 我相信我正在使用您在发布中显示的所有 XSLT。我看到 97 行代码。我通过 Adob​​e Dreamweaver 和 Safari 运行它。
  • 这很奇怪。它似乎在 FireFox 中运行良好(我没有 Dreamweaver 或 Safari)。我已经修改它以使用更直接的方法。你能试一试吗?另外,你能回答我关于结果 XML 应该是什么样子的问题吗?
  • 我通过 Oxygen 运行了 XML,它提供了最终的 XML,如您上面的示例所示。您知道 Dreamweaver 和 Safari 无法处理 XML 的原因吗?我确实从另一个程序收到一条消息,指出 XSL 缺少必需的属性:“document() URI”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
  • 2015-01-20
  • 1970-01-01
  • 1970-01-01
  • 2013-04-17
  • 1970-01-01
相关资源
最近更新 更多