XSLT获取第一个元素节点

时间:2013-02-06 00:13:45

标签: xslt xpath nodes

<SMRCRLT_XML>
 <AREA>
  <DETAILS>
   <DETAIL_REQUIREMENT>
    <RULE_REQUIREMENT>
     <DETAIL_REQUIREMENT>
      <COURSE_ROWSET>
       <COURSE_SET>
        <COURSE_AREA>TESTSELECT</COURSE_AREA>
        <COURSE_KEY_RULE>1200</COURSE_KEY_RULE>
        <COURSE_SET>A</COURSE_SET>
        <COURSE_SUBSET>1</COURSE_SUBSET>
        <COURSE_SUBJ_CODE>CHEM</COURSE_SUBJ_CODE>
        <COURSE_CRSE_NUMB_LOW>345A</COURSE_CRSE_NUMB_LOW>
       </COURSE_SET>
      </COURSE_ROWSET>
     </DETAIL_REQUIREMENT>
     <DETAIL_REQUIREMENT>
      <COURSE_ROWSET>
       <COURSE_SET>
        <COURSE_KEY_RULE>1200</COURSE_KEY_RULE>
        <COURSE_SET>A</COURSE_SET>
        <COURSE_SUBSET>2</COURSE_SUBSET>
        <COURSE_SUBJ_CODE>CHEM</COURSE_SUBJ_CODE>
        <COURSE_CRSE_NUMB_LOW>476A</COURSE_CRSE_NUMB_LOW>
       </COURSE_SET>
      </COURSE_ROWSET>
     </DETAIL_REQUIREMENT>
     <DETAIL_REQUIREMENT>
      <COURSE_ROWSET>
       <COURSE_SET>
        <COURSE_AREA>TESTSELECT</COURSE_AREA>
        <COURSE_KEY_RULE>1200</COURSE_KEY_RULE>
        <COURSE_SET>A</COURSE_SET>
        <COURSE_SUBSET>3</COURSE_SUBSET>
        <COURSE_SUBJ_CODE>PHIL</COURSE_SUBJ_CODE>
        <COURSE_CRSE_NUMB_LOW>432</COURSE_CRSE_NUMB_LOW>
       </COURSE_SET>
      </COURSE_ROWSET>
     </DETAIL_REQUIREMENT>
     <DETAIL_REQUIREMENT>
      <COURSE_ROWSET>
       <COURSE_SET>
        <COURSE_AREA>TESTSELECT</COURSE_AREA>
        <COURSE_KEY_RULE>1200</COURSE_KEY_RULE>
        <COURSE_SET>B</COURSE_SET>
        <COURSE_SUBSET>4</COURSE_SUBSET>
        <COURSE_SUBJ_CODE>PHIL</COURSE_SUBJ_CODE>
        <COURSE_SUBJ_DESC>Philosophy</COURSE_SUBJ_DESC>
        <COURSE_CRSE_NUMB_LOW>433</COURSE_CRSE_NUMB_LOW>
       </COURSE_SET>
      </COURSE_ROWSET>
     </DETAIL_REQUIREMENT>
     <DETAIL_REQUIREMENT>
      <COURSE_ROWSET>
       <COURSE_SET>
        <COURSE_AREA>TESTSELECT</COURSE_AREA>
        <COURSE_KEY_RULE>1200</COURSE_KEY_RULE>
        <COURSE_SET>B</COURSE_SET>
        <COURSE_SUBSET>5</COURSE_SUBSET>
        <COURSE_SUBJ_CODE>ZOOL</COURSE_SUBJ_CODE>
        <COURSE_CRSE_NUMB_LOW>321</COURSE_CRSE_NUMB_LOW>
       </COURSE_SET>
      </COURSE_ROWSET>
     </DETAIL_REQUIREMENT>
     <DETAIL_REQUIREMENT>
      <COURSE_ROWSET>
       <COURSE_SET>
        <COURSE_AREA>TESTSELECT</COURSE_AREA>
        <COURSE_KEY_RULE>1200</COURSE_KEY_RULE>
        <COURSE_SET>B</COURSE_SET>
        <COURSE_SUBSET>6</COURSE_SUBSET>
        <COURSE_SUBJ_CODE>BIOC</COURSE_SUBJ_CODE>
        <COURSE_CRSE_NUMB_LOW>456</COURSE_CRSE_NUMB_LOW>
       </COURSE_SET>
      </COURSE_ROWSET>
     </DETAIL_REQUIREMENT>
    </RULE_REQUIREMENT>
   </DETAIL_REQUIREMENT>
  </DETAILS>
 </AREA>
</SMRCRLT_XML>

我试图从每个COURSE_SET的XML中获取第一个元素,但它返回所有值。有人可以请帮助。这是我申请的模板:

<xsl:apply-templates select="//SMRCRLT_XML/AREA/DETAILS/DETAIL_REQUIREMENT/RULE_REQUIREMENT/DETAIL_REQUIREMENT/COURSE_ROWSET/COURSE_SET[COURSE_AREA='TESTSELECT' and COURSE_KEY_RULE='1200'][1]"/>

我得到的结果是:

CHEM345A
PHIL432
PHIL433
ZOOL321
BIOC456

我要找的结果是CHEM 345A然后是PHIL433

2 个答案:

答案 0 :(得分:2)

这里有几个问题。

首先,XPath表达式中的[1]通过要求选择的COURSE_SET元素是其父级的第一个子级来过滤XPath值。如果没有[1],则XPath表达式为:

//SMRCRLT_XML
/AREA
/DETAILS
/DETAIL_REQUIREMENT
/RULE_REQUIREMENT
/DETAIL_REQUIREMENT
/COURSE_ROWSET
/COURSE_SET
[COURSE_AREA='TESTSELECT' and COURSE_KEY_RULE='1200']

匹配该路径表达式的每个 COURSE_SET是其父级的第一个子级。 (唯一不是第一个孩子的COURSE_SET元素是COURSE_SET的子元素,而不是COURSE_ROWSET的子元素。)

第二个问题是,从您的问题和您尝试制定所需的XPath表达式来判断,您希望以某种方式对课程进行分组(起初我认为您可能希望它们按部门分组,但现在我希望您希望它们按嵌套COURSE_SET元素的值进行分组,在您的示例中,它具有值A或B),因此通过在某个合适的上下文中选择第一个COURSE_SET,您可以获得为每个组列出的第一个课程。但是,您显示的XML实际上并不按部门或课程设置分组课程;它提供了一个没有分组的课程列表。这里没有CHEM 345A和PHIL 433是第一道菜的元素。

如果您的设计要求按部门或课程设置分组课程,那么您的数据源不会提供您想要的数据,您将需要修复它。

另一方面,如果您仍然坚持使用此XML并希望使用XPath来尝试提供数据源无法提供的结构,那么您不要 want&#34;每个COURSE_SET&#34;的第一个元素,你想要&#34;在一个部门(或COURSE_SET)中的每个COURSE_SET与前一个COURSE_SET&#34;不同。而你的XPath表达式可能类似于

//COURSE_ROWSET/COURSE_SET
  [not(COURSE_SET eq preceding::COURSE_SET[1])]

你的第三个问题是你的XML似乎太喜欢为不同的构造使用相同的名称(一组COURSE_SET元素,每个元素包含课程的描述,部门和课程编号等等,以及第二组COURSE_SET元素,包含字符串&#39; A&#39;&#39; B&#39;,两组DETAIL_REQUIREMENT,内容不同等等。对于不熟悉的人来说,这会让人感到困惑数据,它将使每一次细节讨论成为错误传达和错误的机会。

答案 1 :(得分:0)

在XSLT 1.0中处理这样的任务的有效方法是使用Muenchian分组,如下所示:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:key name="kSet" match="COURSE_ROWSET/COURSE_SET" use="COURSE_SET" />

  <xsl:template match="/">
    <root>
      <xsl:apply-templates
        select="//COURSE_ROWSET/COURSE_SET[generate-id() = 
                  generate-id(key('kSet', COURSE_SET)[1])]" />
    </root>
  </xsl:template>

  <xsl:template match="COURSE_ROWSET/COURSE_SET">
    <item>
      <xsl:value-of select="concat(COURSE_SUBJ_CODE, COURSE_CRSE_NUMB_LOW)"/>
    </item>
  </xsl:template>
</xsl:stylesheet>

当此XSLT应用于您的样本输入时,结果为:

<root>
  <item>CHEM345A</item>
  <item>PHIL433</item>
</root>