0

A XSLT newbie here. I have an XML block that can look like anything, however based on its element name, I need to be able to change its content. The problem is that the XML could be prefixed or not.

A prefixed XML might look like:

<POIS xmlns:tns="http://example.com/integration/docs" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <tns:POI>
      <tns:CTL>
         <tns:transaction_date/>
         <tns:record_qualifier/>
         <tns:start_date>2012-10-12 </tns:start_date>
         <tns:test_indicator>P</tns:test_indicator>
       </tns:CTL>
    </tns:POI>
 </tns:POIS>  

Or not Prefixed:

<POIS xmlns="http://example.com/integration/docs"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <POI>
      <CTL>
         <transaction_date/>
         <record_qualifier/>
         <start_date>2012-10-12</start_date>
         <test_indicator>P</test_indicator>
    </CTL>
  </POI>
 </POIS>   

I want to change the content of the element that ends with _date when there is a value.

So a possible output will be:

<POIS xmlns:tns="http://example.com/integration/docs" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
   <tns:POI>
      <tns:CTL>
         <tns:transaction_date/>
         <tns:record_qualifier/>
         <tns:start_date>20121012 </tns:start_date>
         <tns:test_indicator>P</tns:test_indicator>
    </tns:CTL>
   </tns:POI> 
 </tns:POIS>   

This is what I have so far:

The problem is that it complains with tns: namespace on the changed element when prefixed or put a blank namespace for non-prefixed XML element.

Any solutions? This is a utility transformation so I would like to keep it as generic as possible.

    <xsl:stylesheet version="2.0"      
    xmlns:xp20="http://www.oracle.com/XSL/Transform/
    java/oracle.tip.pc.services.functions.Xpath20" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:template match="node()|@*">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

    <xsl:template match="node()[ends-with(name(), '_date')]">
     <xsl:choose>
      <xsl:when test="(text())" >
             <xsl:element name="{name()}" >
      <xsl:value-of select ="xp20:format-dateTime(text(),'[Y0001][M01][D01]')" /> 
      </xsl:element>
      </xsl:when>
      <xsl:otherwise>
     <xsl:copy>
          <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>   
      </xsl:otherwise>
    </xsl:choose>  
       </xsl:template>
    </xsl:stylesheet>
5
  • Your XML is not well-formed: <CTL> should end with </CTL>, missing </POI> closing tag, inconsistent prefixing on <POIS> tag. Please fix your XML. Commented Apr 19, 2012 at 17:00
  • Try changing <xsl:element name="{name()}"> to <xsl:element name="{local-name()}">...does that help? Commented Apr 19, 2012 at 17:23
  • Unfortunately, It still fails, since it is putting a blank namespace '<start_date xmlns="">20120430</start_date>' . Commented Apr 19, 2012 at 19:22
  • Also, I dont even need to add the element if there was any other way to just change the value inside. Commented Apr 19, 2012 at 19:48
  • I was able to fix the issue: <xsl:template match="node()[ends-with(name(), '_date')]//text()"> <xsl:value-of select="xp20:format-dateTime(.,'[Y0001][M01][D01]')"/> </xsl:template> <xsl:template match="node()|@*"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> Commented Apr 19, 2012 at 22:25

1 Answer 1

1

Try changing <xsl:element name="{name()}"> to <xsl:element name="{local-name()}">.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.