XLS select=“$my_parameter” will not evaluate as pa

2019-07-31 04:35发布

Here is a variable that returns 12, which is what I expect:

    <xsl:variable name="MM">
        <xsl:value-of select="../BIRTH_MONTH"/>
    </xsl:variable>

I want to base the select clause on a parameter. I figure something like this:

<!-- $which_date has the value "BIRTH" -->

    <xsl:variable name="MM">
        <xsl:value-of select="concat('../', $which_date, '_MONTH')"/>
    </xsl:variable>

The above returns a value of ../BIRTH_MONTH.

I thought the problem might be with concat(), but below is a variant that also returns the un-evaluated result of ../BIRTH_MONTH:

<!-- $which_date has the value "../BIRTH_MONTH" -->

    <xsl:variable name="MM">
        <xsl:value-of select="$which_date"/>
    </xsl:variable>

(Insert history here of dozens of attempts based on tweaks with quotation marks, braces, etc...)

How can I use $which_date in an expression that can be evaluated?

标签: xslt
1条回答
看我几分像从前
2楼-- · 2019-07-31 05:30
<xsl:variable name="MM">
    <xsl:value-of select="concat('../', $which_date, '_MONTH')"/>
</xsl:variable>

The above returns a value of ../BIRTH_MONTH.

You want:

<xsl:variable name="MM" select="../*[name()=concat($which_date, '_MONTH')]"/>

Here is a complete transformation:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>
 <xsl:param name="which_date" select="'BIRTH'"/>

  <xsl:template match="x">
    <xsl:variable name="MM" select=
         "../*[name()=concat($which_date, '_MONTH')]"/>
    <xsl:value-of select="$MM"/>
  </xsl:template>

  <xsl:template match="text()"/>
</xsl:stylesheet>

When this transformation is applied on the following XML document (none was provided with the question):

<t>
 <x>1</x>
 <BIRTH_MONTH>12</BIRTH_MONTH>
</t>

the wanted, correct result is produced:

12

Update: Based on your other similar question, we see that you want a parameterized solution.

Here is one possible parameterized solution:

<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:param name="pdateComponents" select="'|BIRTH_MONTH|BIRTH_DAY|BIRTH_YEAR|'"/>
 <xsl:param name="poutputDateName" select="'BIRTH_DATE'"/>

  <xsl:template match="/*">
    <xsl:apply-templates select=
     "*[*[contains($pdateComponents, concat('|',name(),'|'))]]" mode="dateHolder"/>
  </xsl:template>

  <xsl:template match="*" mode="dateHolder">
    <xsl:copy>
      <xsl:copy-of select="@*"/>
      <xsl:element name="{$poutputDateName}">
        <xsl:apply-templates select=
        "*[contains($pdateComponents, concat('|',name(),'|'))]" mode="date">
          <xsl:sort select="substring-before($pdateComponents, concat('|',name(),'|'))"/>
        </xsl:apply-templates>
      </xsl:element>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="*" mode="date">
    <xsl:value-of select=
         "concat(substring('/', 1 + (position() = 1)), normalize-space())"/>
  </xsl:template>
</xsl:stylesheet>

When this XSLT 1.0 transformation is applied on the following XML document:

<RECORDS>
    <PERSON name="A">
        <BIRTH_YEAR> 1943 </BIRTH_YEAR>
        <BIRTH_MONTH>  04 </BIRTH_MONTH>
        <BIRTH_DAY>    01 </BIRTH_DAY>
    </PERSON>
    <PERSON name="B">
        <BIRTH_YEAR> 1957 </BIRTH_YEAR>
        <BIRTH_MONTH>  08 </BIRTH_MONTH>
        <BIRTH_DAY>    29 </BIRTH_DAY>
    </PERSON>
    <PERSON name="C">
        <BIRTH_YEAR> 1802 </BIRTH_YEAR>
        <BIRTH_MONTH>  12 </BIRTH_MONTH>
        <BIRTH_DAY>    14 </BIRTH_DAY>
    </PERSON>
    <PERSON name="D">
        <BIRTH_YEAR> 2015 </BIRTH_YEAR>
        <BIRTH_MONTH>  04 </BIRTH_MONTH>
        <BIRTH_DAY>    30 </BIRTH_DAY>
    </PERSON>
</RECORDS>

the result is:

<PERSON name="A">
   <BIRTH_DATE>04/01/1943</BIRTH_DATE>
</PERSON>
<PERSON name="B">
   <BIRTH_DATE>08/29/1957</BIRTH_DATE>
</PERSON>
<PERSON name="C">
   <BIRTH_DATE>12/14/1802</BIRTH_DATE>
</PERSON>
<PERSON name="D">
   <BIRTH_DATE>04/30/2015</BIRTH_DATE>
</PERSON>

Do note:

  1. The names of the date components are provided in a global parameter to the transformation -- they are not statically known.
  2. The name of the output element to contain the date is also provided as the value of another global parameter to the transformation.
  3. Even the order of the date components, using which to construct the date, is provided in the first component!

Thus, the above supplied parameter results in American dates output.

But if we provide this parameter:

 <xsl:param name="pdateComponents" select="'|BIRTH_DAY|BIRTH_MONTH|BIRTH_YEAR|'"/>

then the result of the transformation contains dates in European format:

<PERSON name="A">
   <BIRTH_DATE>01/04/1943</BIRTH_DATE>
</PERSON>
<PERSON name="B">
   <BIRTH_DATE>29/08/1957</BIRTH_DATE>
</PERSON>
<PERSON name="C">
   <BIRTH_DATE>14/12/1802</BIRTH_DATE>
</PERSON>
<PERSON name="D">
   <BIRTH_DATE>30/04/2015</BIRTH_DATE>
</PERSON>
查看更多
登录 后发表回答