Home > Mobile >  Valid XSL Transform won't parse in c#
Valid XSL Transform won't parse in c#

Time:12-15

I have this XML input:

<?xml version="1.0"?>
<xc:XmlCache xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">
  <xc:XmlCacheArea xc:value="MarketParameters">
    <mp:nickName xmlns:mp="mx.MarketParameters" xc:value="BO">
      <mp:date xc:value="20211208">
        <rt:rate xmlns:rt="mx.MarketParameters.Rates">
          <rtcu:curve xmlns:rtcu="mx.MarketParameters.Rates.Curve">
            <rtcu:currency xc:value="USD">
              <rtcu:label xc:value="USD: SOV_ZC">
                <rtcu:type xc:value="Swap">
                  <rtcu:generator xc:value="USD S TREAS">
                    <rtcu:market xc:value="">
                      <rtcu:maturity xc:value="10Y" xc:dates="20211210-20311210" xc:type="Fields">
                        <mp:askConvexitySpread xc:keyFormat="N">0</mp:askConvexitySpread>
                        <mp:askCurveSpread xc:keyFormat="N">0.000000000</mp:askCurveSpread>
                        <mp:askDiscount xc:keyFormat="N">0.864632927818374</mp:askDiscount>
                        <mp:askDiscountBasisSpread xc:keyFormat="N"/>
                        <mp:askMarketQuote xc:keyFormat="N">1.446068284</mp:askMarketQuote>
                        <mp:askZeroCoupon xc:keyFormat="N">1.45291000006736</mp:askZeroCoupon>
                        <mp:askZeroCouponBasisSpread xc:keyFormat="N"/>
                        <mp:askZeroCouponSpread xc:keyFormat="N">0.000000000</mp:askZeroCouponSpread>
                        <mp:bidConvexitySpread xc:keyFormat="N">0</mp:bidConvexitySpread>
                        <mp:bidCurveSpread xc:keyFormat="N">0.000000000</mp:bidCurveSpread>
                        <mp:bidDiscount xc:keyFormat="N">0.864632927818374</mp:bidDiscount>
                        <mp:bidDiscountBasisSpread xc:keyFormat="N"/>
                        <mp:bidMarketQuote xc:keyFormat="N">1.446068284</mp:bidMarketQuote>
                        <mp:bidZeroCoupon xc:keyFormat="N">1.45291000006736</mp:bidZeroCoupon>
                        <mp:bidZeroCouponBasisSpread xc:keyFormat="N"/>
                        <mp:bidZeroCouponSpread xc:keyFormat="N">0.000000000</mp:bidZeroCouponSpread>
                        <mp:frontierDate xc:keyFormat="N">0</mp:frontierDate>
                        <mp:intervalSplineEta xc:keyFormat="N">-1</mp:intervalSplineEta>
                        <mp:midConvexitySpread xc:keyFormat="N">0</mp:midConvexitySpread>
                        <mp:midCurveSpread xc:keyFormat="N">0.000000000</mp:midCurveSpread>
                        <mp:midDiscount xc:keyFormat="N">0.864632927818374</mp:midDiscount>
                        <mp:midDiscountBasisSpread xc:keyFormat="N"/>
                        <mp:midMarketQuote xc:keyFormat="N">1.446068284</mp:midMarketQuote>
                        <mp:midZeroCoupon xc:keyFormat="N">1.45291000006736</mp:midZeroCoupon>
                        <mp:midZeroCouponBasisSpread xc:keyFormat="N"/>
                        <mp:midZeroCouponSpread xc:keyFormat="N">0.000000000</mp:midZeroCouponSpread>
                        <mp:selected xc:keyFormat="N">1</mp:selected>
                      </rtcu:maturity>
                      <rtcu:maturity xc:value="15Y" xc:dates="20211210-20361210" xc:type="Fields">
                        <mp:askConvexitySpread xc:keyFormat="N">0</mp:askConvexitySpread>
                        <mp:askCurveSpread xc:keyFormat="N">0.000000000</mp:askCurveSpread>
                        <mp:askDiscount xc:keyFormat="N">0.769521955887512</mp:askDiscount>
                        <mp:askDiscountBasisSpread xc:keyFormat="N"/>
                        <mp:askMarketQuote xc:keyFormat="N">1.716406662</mp:askMarketQuote>
                        <mp:askZeroCoupon xc:keyFormat="N">1.74466000012162</mp:askZeroCoupon>
                        <mp:askZeroCouponBasisSpread xc:keyFormat="N"/>
                        <mp:askZeroCouponSpread xc:keyFormat="N">0.000000000</mp:askZeroCouponSpread>
                        <mp:bidConvexitySpread xc:keyFormat="N">0</mp:bidConvexitySpread>
                        <mp:bidCurveSpread xc:keyFormat="N">0.000000000</mp:bidCurveSpread>
                        <mp:bidDiscount xc:keyFormat="N">0.769521955887512</mp:bidDiscount>
                        <mp:bidDiscountBasisSpread xc:keyFormat="N"/>
                        <mp:bidMarketQuote xc:keyFormat="N">1.716406662</mp:bidMarketQuote>
                        <mp:bidZeroCoupon xc:keyFormat="N">1.74466000012162</mp:bidZeroCoupon>
                        <mp:bidZeroCouponBasisSpread xc:keyFormat="N"/>
                        <mp:bidZeroCouponSpread xc:keyFormat="N">0.000000000</mp:bidZeroCouponSpread>
                        <mp:frontierDate xc:keyFormat="N">0</mp:frontierDate>
                        <mp:intervalSplineEta xc:keyFormat="N">-1</mp:intervalSplineEta>
                        <mp:midConvexitySpread xc:keyFormat="N">0</mp:midConvexitySpread>
                        <mp:midCurveSpread xc:keyFormat="N">0.000000000</mp:midCurveSpread>
                        <mp:midDiscount xc:keyFormat="N">0.769521955887512</mp:midDiscount>
                        <mp:midDiscountBasisSpread xc:keyFormat="N"/>
                        <mp:midMarketQuote xc:keyFormat="N">1.716406662</mp:midMarketQuote>
                        <mp:midZeroCoupon xc:keyFormat="N">1.74466000012162</mp:midZeroCoupon>
                        <mp:midZeroCouponBasisSpread xc:keyFormat="N"/>
                        <mp:midZeroCouponSpread xc:keyFormat="N">0.000000000</mp:midZeroCouponSpread>
                        <mp:selected xc:keyFormat="N">1</mp:selected>
                      </rtcu:maturity>
                    </rtcu:market>
                  </rtcu:generator>
                </rtcu:type>
              </rtcu:label>
            </rtcu:currency>
          </rtcu:curve>
        </rt:rate>
      </mp:date>
    </mp:nickName>
  </xc:XmlCacheArea>
</xc:XmlCache>

I am using this transform :

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mp="mx.MarketParameters" xmlns:xc="xmlCache" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">
    <xsl:template match="/">
        <data>
            <xsl:apply-templates select="*"/>
        </data>
    </xsl:template>
    <xsl:template match="rtcu:maturity">
        <row>
<xsl:attribute name="Cle"><xsl:value-of select="../../../../../@*:value"/>;<xsl:value-of select="../../../../@*:value"/>;<xsl:value-of select="../../../@*:value"/>;<xsl:value-of select="../../@*:value"/>;<xsl:value-of select="../@*:value"/>;<xsl:value-of select="@*:value"/></xsl:attribute>
<xsl:attribute name="Source1"><xsl:value-of select="mp:askZeroCoupon"/></xsl:attribute>
<xsl:attribute name="Source2"><xsl:value-of select="mp:bidZeroCoupon"/></xsl:attribute>
<xsl:attribute name="Source3"><xsl:value-of select="mp:midZeroCoupon"/></xsl:attribute>
        </row>
    </xsl:template>
</xsl:stylesheet>

And the result is as expected when I use the validator here: https://www.freeformatter.com/xsl-transformer.html

<data xmlns:mp="mx.MarketParameters"
      xmlns:xc="xmlCache"
      xmlns:rt="mx.MarketParameters.Rates"
      xmlns:rtcu="mx.MarketParameters.Rates.Curve">
   <row Cle="USD;USD: SOV_ZC;Swap;USD S TREAS;;10Y"
        Source1="1.45291000006736"
        Source2="1.45291000006736"
        Source3="1.45291000006736"/>
   <row Cle="USD;USD: SOV_ZC;Swap;USD S TREAS;;15Y"
        Source1="1.74466000012162"
        Source2="1.74466000012162"
        Source3="1.74466000012162"/>
</data>

However when I run this transform in a C# app and call the Load() function in XslCompiledTransform when I pass it this transform above, it fails with the error

Expected end of the expression, found `':'.\r\n../../../../../@* -->:<--`

It basically refuses to check the other namespaces for the attribute I'm looking for on this node.

I know that the attributes are in the xc namespace but when I use the xc: namespace to get the attribute values to build my key like so:

<xsl:value-of select="@xc:value"/>

The values are all null which results in a key that looks like this in the output:

<row Cle=";;;;;"

No bueno!

How can I output the values of all the xc:value attributes from these tags:

<rtcu:currency xc:value="USD">
              <rtcu:label xc:value="USD: SOV_ZC">
                <rtcu:type xc:value="Swap">
                  <rtcu:generator xc:value="USD S TREAS">
                    <rtcu:market xc:value="">
                      <rtcu:maturity xc:value="10Y"

into my key row:

<row Cle="USD;USD: SOV_ZC;Swap;USD S TREAS;;10Y"

while not triggering a parsing error in the c# Load() function?

CodePudding user response:

There are two errors in your code:

  1. Namespace wildcards like *:value are a feature of XPath-2.0 and above

    Local name tests (namespace wildcards) were eventually added to XPath 2.0

    So you can't use them in your XSLT-1.0 code

  2. You have a typo in your xc: namespace declaration:

    1. In your XML it's xmlns:xc="XmlCache"
    2. In your XSLT it's xmlns:xc="xmlCache"

If you fix both, the code should work as desired.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:mp="mx.MarketParameters" xmlns:xc="XmlCache" xmlns:rt="mx.MarketParameters.Rates" xmlns:rtcu="mx.MarketParameters.Rates.Curve">

    <xsl:template match="/">
        <data>
            <xsl:apply-templates select="*"/>
        </data>
    </xsl:template>
    
    <xsl:template match="rtcu:maturity">
        <row>
            <xsl:attribute name="Cle"><xsl:value-of select="../../../../../@xc:value"/>;<xsl:value-of select="../../../../@xc:value"/>;<xsl:value-of select="../../../@xc:value"/>;<xsl:value-of select="../../@xc:value"/>;<xsl:value-of select="../@xc:value"/>;<xsl:value-of select="@xc:value"/></xsl:attribute>
            <xsl:attribute name="Source1"><xsl:value-of select="mp:askZeroCoupon"/></xsl:attribute>
            <xsl:attribute name="Source2"><xsl:value-of select="mp:bidZeroCoupon"/></xsl:attribute>
            <xsl:attribute name="Source3"><xsl:value-of select="mp:midZeroCoupon"/></xsl:attribute>
        </row>
    </xsl:template>
</xsl:stylesheet>

BTW you can simplify one of your expressions to

<xsl:attribute name="Cle"><xsl:for-each select="ancestor-or-self::rtcu:*"><xsl:value-of select="@xc:value"/><xsl:if test="position()!=last() and position()!=1">;</xsl:if></xsl:for-each></xsl:attribute>

This concatenates the xc:value attributes of all rtcu:* ancestors. Maybe that's of some use to you.

  • Related