4

I have been trying to transform an XML file using XSLT but due to some problem, namely "xmlns", It is not transforming. I, for the life of me can't find what is wrong.

The XML file:

<?xml version="1.0" encoding="utf-8"?>
<restoreCredit fpmlVersion="5-6" 
xsi:schemaLocation="http://www.fpml.org/FpML-5/pretrade d:\_Test\_PM\FpML\5.6\pretrade\fpml-main-5-6.xsd" 
xmlns="http://www.fpml.org/FpML-5/pretrade" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <header>
        <messageId messageIdScheme="http://www.test.com/fpml">4000001</messageId>
        <sentBy>Test</sentBy>
        <sendTo>SEF1</sendTo>
        <creationTimestamp>2012-07-25T08:57:00Z</creationTimestamp>
    </header>
    <parentCorrId corrIdScheme="http://www.test.com/fpml">RestoreCreditOnSEF</parentCorrId>
    <corrId corrIdScheme="http://www.test.com/fpml">4000123</corrId>
    <sqNumber>1</sqNumber>

    <party id="cb12">
        <partyId>CM1</partyId>
    </party>
    <account id="acc1">
        <accountId>account112</accountId>
    </account>
</restoreCredit>

This is the XSLT File:

<xsl:stylesheet version="1.0" 
xmlns="http://www.fpml.org/FpML-5/pretrade"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.fpml.org/FpML-5/pretrade d:\_test\_PM\FpML\5.6\pretrade\fpml-main-5-6.xsd" 
>

<xsl:output method ="xml" indent="yes"/>

  <!-- NOTE: All tags have been checked if present, if not , the tags will not be shown in the output -->
  <xsl:strip-space elements= "*"/>

  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="rCredit">
    <rCredit>
      <xsl:if test="header">
        <!-- Header  -->
        <header>
          <FpHdMsgID>
            <xsl:attribute name = "FpHdMsgIDScheme">
              <xsl:value-of select = "header/messageId/@messageIdScheme" />
            </xsl:attribute>
            <xsl:value-of select = "header/messageId"/>
          </FpHdMsgID>

          <FpHdSentBy>
            <xsl:value-of select = "header/sentBy" />
          </FpHdSentBy>

          <FpHdSentTo>
            <xsl:value-of select="header/sendTo" />
          </FpHdSentTo>

          <FpHdCreateTime>
            <xsl:value-of select= "header/creationTimestamp" />
          </FpHdCreateTime>

          <xsl:if test = "header/expiryTimeStamp">
            <FpHdExpTime>
              <xsl:value-of select= "header/expiryTimeStamp" />
            </FpHdExpTime>
          </xsl:if>
        </header>
      </xsl:if>

      <!-- parentCorrId -->
      <xsl:if test="parentCorrId">
        <FpParentCorID>
          <xsl:attribute name = "FpParentCorIDCorSch">
            <xsl:value-of select = "parentCorrId/@corrIdScheme" />
          </xsl:attribute>
          <xsl:value-of select = "parentCorrId"/>
        </FpParentCorID>
      </xsl:if>

      <!-- corrId -->
      <xsl:if test="corrId">
        <FpCorID>
          <xsl:attribute name = "FpCorIDSch">
            <xsl:value-of select = "corrId/@corrIdScheme" />
          </xsl:attribute>
          <xsl:value-of select = "corrId"/>
        </FpCorID>
      </xsl:if>

      <!-- sqNumber -->
      <xsl:if test="sqNumber">
        <FpSeqNum>
          <xsl:value-of select="sqNumber"/>
        </FpSeqNum>
      </xsl:if>

      <!-- party -->
      <xsl:if test="party">
        <FpPartyID>
          <xsl:value-of select = "party/@id" />
        </FpPartyID>

        <FpPartyIDValue>
          <xsl:value-of select = "party/partyId" />
        </FpPartyIDValue>
      </xsl:if>

      <!-- account -->
      <xsl:if test="account">
        <FpAccountId>
          <xsl:value-of select="account/@id"/>
        </FpAccountId>

        <FpAccountIdAcc>
          <xsl:value-of select="account/accountId"/>
        </FpAccountIdAcc>
      </xsl:if>

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

Expected Ouput:

<?xml version="1.0" encoding="UTF-8"?>
<restoreCredit xmlns="http://www.fpml.org/FpML-5/pretrade" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <header>
        <FpHdMsgID FpHdMsgIDScheme="http://www.test.com/fpml">4000001</FpHdMsgID>
        <FpHdSentBy>Test</FpHdSentBy>
        <FpHdSentTo>SEF1</FpHdSentTo>
        <FpHdCreateTime>2012-07-25T08:57:00Z</FpHdCreateTime>
    </header>
    <FpParentCorID FpParentCorIDCorSch="http://www.test.com/fpml">RestoreCreditOnSEF</FpParentCorID>
    <FpCorID FpCorIDSch="http://www.test.com/fpml">4000123</FpCorID>
    <FpSeqNum>1</FpSeqNum>
    <FpPartyID>cb12444</FpPartyID>
    <FpPartyIDValue>CM1</FpPartyIDValue>
    <FpAccountId>acc1</FpAccountId>
    <FpAccountIdAcc>account1</FpAccountIdAcc>
</restoreCredit>

Resulting Output:

<?xml version="1.0" encoding="UTF-8"?>
<restoreCredit xmlns="http://www.fpml.org/FpML-5/pretrade" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" fpmlVersion="5-6" xsi:schemaLocation="http://www.fpml.org/FpML-5/pretrade d:\_test\_PM\FpML\5.6\pretrade\fpml-main-5-6.xsd">
    <header>
        <messageId messageIdScheme="http://www.test.com/fpml">4000001</messageId>
        <sentBy>test</sentBy>
        <sendTo>SEF1</sendTo>
        <creationTimestamp>2012-07-25T08:57:00Z</creationTimestamp>
    </header>
    <parentCorrId corrIdScheme="http://www.test.com/fpml">RestoreCreditOnSEF</parentCorrId>
    <corrId corrIdScheme="http://www.test.com/fpml">4000123</corrId>
    <sqNumber>1</sqNumber>
    <party id="c3321">      
        <partyId>CM1</partyId>
    </party>
    <account id="acc1">
        <accountId>account12</accountId>  
    </account>
</restoreCredit>

The expected output only comes when I remove xmlns="http://www.fpml.org/FpML-5/pretrade"

This also works if, In the XML file, I add a tag to "xmlns" Eg xmlns:AAA="http://www.fpml.org/FpML-5/pretrade" But I have to transform this without editing the XML file.

  • you have to register the namespace in your xslt file and refer to that in all your xpaths. For example `xmlns:abc="http://www.fpml.org/FpML-5/pretrade"` and `` – Joel M. Lamsen Mar 23 '15 at 09:27
  • Is there anyway do this without editing the XML at all? –  Mar 23 '15 at 09:32
  • Also I'm really sorry, in the XSLT file, "xmlns:t" should have been only "xmlns" –  Mar 23 '15 at 09:37
  • There are hundreds of posts on here asking the same question, the one I've marked as the duplicate was my first hit on Google for "XSLT default namespace". You were half way there in the original form of the question having declared the `xmlns:t` in your stylesheet, but you need to actually _use_ that prefix in your XPath expressions like `t:header/t:messageId` – Ian Roberts Mar 23 '15 at 09:54
  • I'm not sure what happened to my close vote, I was referring to http://stackoverflow.com/questions/1344158/xslt-with-xml-source-that-has-a-default-namespace-set-to-xmlns – Ian Roberts Mar 23 '15 at 09:56
  • @IanRoberts I'm really sorry, it was a mistake, Its only "xmlns" –  Mar 23 '15 at 09:58
  • @IanRoberts I have taken the liberty of overriding your vote. The other question that you have linked to does not have the added complication of a default namespace for the output. – michael.hor257k Mar 23 '15 at 10:01
  • possible duplicate of [Trouble matching XML elements that has namespace attribute](http://stackoverflow.com/questions/3615222/trouble-matching-xml-elements-that-has-namespace-attribute) – nwellnhof Mar 23 '15 at 12:06
  • @michael.hor257k How is the default output namespace a complication in the context of this question? Anyway, you can easily find duplicate questions that also have a default output namespace. Let's please close questions like this as duplicate. As Ian said, this must have been asked 100 times already. – nwellnhof Mar 23 '15 at 12:18
  • @nwellnhof "*How is the default output namespace a complication in the context of this question?*" I still remember when I struggled with his concept. -- "*As Ian said, this must have been asked 100 times already.*" So? Why does it bother *you* that I have chosen to spend *my* time and *my* effort to answer it for the 101st time? – michael.hor257k Mar 23 '15 at 12:41
  • @michael.hor257k Answering duplicates is usually a waste of time. Assuming that the moderation system works, this question will eventually be closed and probably deleted. – nwellnhof Mar 23 '15 at 12:53
  • 1
    I've rolled back your edit because the question and answers don't make sense without the sample input, output and current XSLT. Remember that the full revision history of all SO posts is public, so if you were trying to remove "confidential" information then simply editing the question like that won't help anyway. If you included sensitive information in the question by mistake then you'd need to flag it for moderator attention and ask that the whole question be deleted. – Ian Roberts Jul 14 '15 at 11:45

1 Answers1

7

The elements in your XML source are in the xmlns="http://www.fpml.org/FpML-5/pretrade" namespace. You must declare this namespace in your stylesheet, assign it a prefix, and use that prefix when selecting or matching the elements in your XML. Here's a minimized example:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fmpl="http://www.fpml.org/FpML-5/pretrade"
xmlns="http://www.fpml.org/FpML-5/pretrade"
exclude-result-prefixes="fmpl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:template match="/fmpl:restoreCredit">
    <restoreCredit>
        <header>
            <FpHdMsgID>
                <xsl:attribute name="FpHdMsgIDScheme">
                    <xsl:value-of select="fmpl:header/fmpl:messageId/@messageIdScheme" />
                </xsl:attribute>
                <xsl:value-of select="fmpl:header/fmpl:messageId"/>
          </FpHdMsgID>
        </header>
    </restoreCredit>
</xsl:template>

</xsl:stylesheet>

When this is applied to your input example, the result will be:

<?xml version="1.0" encoding="utf-8"?>
<restoreCredit xmlns="http://www.fpml.org/FpML-5/pretrade">
  <header>
    <FpHdMsgID FpHdMsgIDScheme="http://www.traiana.com/fpml">4000001</FpHdMsgID>
  </header>
</restoreCredit>

IMPORTANT:

Note the double declaration of the same namespace:

xmlns:fmpl="http://www.fpml.org/FpML-5/pretrade"
xmlns="http://www.fpml.org/FpML-5/pretrade"
  • The first declaration, the one that assigns the fpml prefix, is intended to enable you to address the elements in the input XML.

  • The second declaration declares a default namespace for the stylesheet itself: any literal element you write into the stylesheet - such as the <header> in the example - will be placed into the default namespace.

The fact that two namespaces are the same (i.e. have the same URI) could be said to be a coincidence.

michael.hor257k
  • 113,275
  • 6
  • 33
  • 51
  • Thank you for your answer michael.hor257k!! but is there anyway to do this without editing the XML file at all? –  Mar 23 '15 at 10:02
  • @Shn It is not necessary to edit the XML file at all; it's all done in the XSLT stylesheet. – michael.hor257k Mar 23 '15 at 10:04