在输入XML的情况下,如何使XSL产生以下结果

时间:2012-01-11 16:37:57

标签: xml xslt

我尝试了几件事......使用变量和模板,并且进展缓慢。但我只是没有让这个工作 - 我的上下文遇到了麻烦。

输入......

  • 表'700'可以包含多个条目。
  • Subject1,Subject2,Subject3的值将是英语,数学,科学(但顺序可能因源XML而异)
  • 分数与主题的位置关系(即分数1代表Subject1)

OutPut ......

  • 总是包含6个节点(英语,数学,科学,班级,班级2,班级3)
  • Subject_标签顺序总是需要英语,数学,然后是科学。
  • Subject_标签将为大写
  • 如果相应的分数> 1,则Subject_标签将包含标志1。 0;否则为0
  • Class_Score标签订单总是需要英语,数学,然后是科学。

我修改了我的代码,以下内容可能无法完全正常运行,但会对我尝试过的内容进行分析。

我的第一个问题是 - 我是否走在正确的轨道上?

  • 将主题传递给成绩模板
  • 捕获主题的'索引'
  • 将主题和索引传递给add-Grades-nodes模板

这是我的上下文问题阻止我的地方。

- 我的输入XML -

<?xml version="1.0"?>
<Account Number="123456">
  <Data>
    <Table ID="700">
      <Record ID="1" SubClass="Person">
        <Name.Last>Smith</Name.Last>
        <Name.First>John</Name.First>
        <Score1>50</Score1>
        <Score2>75</Score2>
        <Score3>100</Score3>
        <Subject1>Math</Subject1>
        <Subject2>English</Subject2>
        <Subject3>Science</Subject3>
      </Record>
      <Record ID="2" SubClass="Person">
        <Name.Last>Smith</Name.Last>
        <Name.First>Jane</Name.First>
        <Score1></Score1>
        <Score2>77</Score2>
        <Score3>80</Score3>
        <Subject1>Math</Subject1>
        <Subject2>English</Subject2>
        <Subject3>Science</Subject3>
      </Record>
    </Table>
  </Data>
</Account>

- 所需的输出XML -

<Out>
    <Subject_ENGLISH>1</Subject_ENGLISH>
    <Subject_MATH>1</Subject_MATH>
    <Subject_SCIENCE>1</Subject_SCIENCE>
    <Class_SCORE>75</Class_SCORE>
    <Class2_SCORE>50</Class2_SCORE>
    <Class3_SCORE>100</Class3_SCORE>
    <Subject_ENGLISH>0</Subject_ENGLISH>
    <Subject_MATH>1</Subject_MATH>
    <Subject_SCIENCE>1</Subject_SCIENCE>
    <Class_SCORE></Class_SCORE>
    <Class2_SCORE>77</Class2_SCORE>
    <Class3_SCORE>80</Class3_SCORE>
</Out>

- 当前不起作用的XSLT -

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" version="1.0">
  <xsl:output method="xml" encoding="UTF-8"/>

  <xsl:template match="Account">
    <Out>
      <xsl:for-each select="/Account/Data/Table[@ID='700']/Record[@SubClass='Person']>

        <xsl:call-template name="Grades">
          <xsl:with-param name="Subject">English</xsl:with-param>
        </xsl:call-template>
        <xsl:call-template name="Grades">
          <xsl:with-param name="Subject">Math</xsl:with-param>
        </xsl:call-template>
        <xsl:call-template name="Grades">
          <xsl:with-param name="Subject">Science</xsl:with-param>
        </xsl:call-template>


      </xsl:for-each>
    </Out>
  </xsl:template>


  <xsl:template name="Grades">
    <xsl:param name="Subject"/>

    <xsl:for-each select="*[starts-with(name(), 'Subject')][node()=$Subject]">

      <xsl:variable name='cr-index'>
        <xsl:value-of select ='substring(name(), string-length(name()))'/>
      </xsl:variable>

      <xsl:call-template name="create-Grades-nodes">
        <xsl:with-param name="cr-context" select =".."/>
        <xsl:with-param name="Subject">
          <xsl:value-of select='$Subject' />
        </xsl:with-param>
        <xsl:with-param name="cr-index">
          <xsl:value-of select='$cr-index'/>
        </xsl:with-param>
      </xsl:call-template>
    </xsl:for-each>
  </xsl:template>

  <xsl:template name="create-Grades-nodes" match="$cr-context" >
    <xsl:param name ="cr-context"/>
    <xsl:param name ="Subject"/>
    <xsl:param name ="cr-index"/>

    <xsl:variable name='cr-score'>
      <xsl:value-of select='name($cr-context)/concat("Score", $cr-index)'/>
    </xsl:variable>

    <xsl:variable name="smallcase" select="'abcdefghijklmnopqrstuvwxyz'" />
    <xsl:variable name="uppercase" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'" />

      <xsl:element name='{concat("Subject_", translate($Subject, $smallcase, $uppercase))}'>
        <xsl:choose>
        <xsl:when test= '$cr-score &gt; 0'>
          <xsl:value-of select = "1"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select = "0"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:element>

  </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:4)

此转化:

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

 <xsl:param name="pSubjects">
  <s name="English" at="1"/>
  <s name="Math"    at="2"/>
  <s name="Science" at="3"/>
 </xsl:param>

 <xsl:variable name="vSubjects" select=
 "document('')/*/xsl:param[@name='pSubjects']/*"/>

 <xsl:variable name="vLower" select=
  "'abcdefghijklmnopqrstuvwxyz'"/>

 <xsl:variable name="vUpper" select=
  "'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>

 <xsl:template match="/*">
  <Out>
   <xsl:apply-templates/>
  </Out>
 </xsl:template>

 <xsl:template match="Table[@ID='700']/Record">
  <xsl:apply-templates select="*[starts-with(name(), 'Su')]">
    <xsl:sort select="$vSubjects[@name = current()]/@at" data-type="number"/>
  </xsl:apply-templates>

  <xsl:apply-templates select="*[starts-with(name(), 'Sc')]">
   <xsl:sort select=
    "$vSubjects[@name
               = current()/../*[starts-with(name(), 'Su')]
                    [substring-after(name(), 'Subject')
                    =
                     substring-after(name(current()), 'Score')
                    ]
                ]/@at"
     data-type="number"/>
  </xsl:apply-templates>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'Su')]">
   <xsl:variable name="vgenName" select=
   "concat('Subject_',
            translate(., $vLower, $vUpper)
           )"/>
  <xsl:element name="{$vgenName}">
    <xsl:value-of select="."/>
  </xsl:element>
 </xsl:template>

 <xsl:template match="*[starts-with(name(), 'Sc')]">
  <xsl:variable name="vInd" select=
   "$vSubjects[@name
               = current()/../*[starts-with(name(), 'Su')]
                    [substring-after(name(), 'Subject')
                    =
                     substring-after(name(current()), 'Score')
                    ]
                ]/@at"/>

  <xsl:variable name="vgenName" select=
   "concat('Class',
           translate($vInd, '1', ''),
           '_SCORE'
           )
   "/>
   <xsl:element name="{$vgenName}">
    <xsl:value-of select="."/>
   </xsl:element>
 </xsl:template>
</xsl:stylesheet>

应用于提供的XML文档

<Account Number="123456">
  <Data>
    <Table ID="700">
      <Record ID="1" SubClass="Person">
        <Name.Last>Smith</Name.Last>
        <Name.First>John</Name.First>
        <Score1>50</Score1>
        <Score2>75</Score2>
        <Score3>100</Score3>
        <Subject1>Math</Subject1>
        <Subject2>English</Subject2>
        <Subject3>Science</Subject3>
      </Record>
      <Record ID="2" SubClass="Person">
        <Name.Last>Smith</Name.Last>
        <Name.First>Jane</Name.First>
        <Score1></Score1>
        <Score2>77</Score2>
        <Score3>80</Score3>
        <Subject1>Math</Subject1>
        <Subject2>English</Subject2>
        <Subject3>Science</Subject3>
      </Record>
    </Table>
  </Data>
</Account>

生成想要的正确结果

<Out>
  <Subject_ENGLISH>English</Subject_ENGLISH>
  <Subject_MATH>Math</Subject_MATH>
  <Subject_SCIENCE>Science</Subject_SCIENCE>
  <Class_SCORE>75</Class_SCORE>
  <Class2_SCORE>50</Class2_SCORE>
  <Class3_SCORE>100</Class3_SCORE>
  <Subject_ENGLISH>English</Subject_ENGLISH>
  <Subject_MATH>Math</Subject_MATH>
  <Subject_SCIENCE>Science</Subject_SCIENCE>
  <Class_SCORE>77</Class_SCORE>
  <Class2_SCORE></Class2_SCORE>
  <Class3_SCORE>80</Class3_SCORE>
</Out>