0

I have a xml file who contains multiple elements with same name but differents attributes.

<ns3:ExportMedicines>
  <ns3:Jkm code="35897">
    <ns3:Data from="2016-10-01" to="2020-07-21">
      <ns2:Name>
        <Fr>estradiol 1 mg comp + estradiol 1 mg + dydrogestérone 10 mg comp</Fr> 
      </ns2:Name>
    </ns3:Data>
    <ns3:Data from="2020-07-22">
      <ns2:Name>
        <Fr>estradiol 1 mg comp+ estradiol 1 mg + dydrogestérone 10 mg comp</Fr>
      </ns2:Name>
    </ns3:Data>
  </ns3:Jkm>
</ns3:ExportMedicines>

I would like to get the more recent <ns3:data> element. I'm using xsl 1.0 so as i already read i can't test date attributes. So i think one way to do is to test if the attribute to doesn't exists.

I can't use a template match because i'm already in a for-each

Here is a snippet from my xsl :

<xsl:for-each select="ns3:jkm">
  <xsl:text>INSERT INTO JKM VALUES ('</xsl:text>
  <xsl:value-of select="@code" />
  <xsl:text>','</xsl:text>
  <!--<xsl:if test="not(ns3:Data[@to])">-->
    <xsl:value-of select="ns3:Data/@from and ns3:Data[not(@to)]" /> <!--doesn't work-->
  <xsl:text>','</xsl:text>
  <!--</xsl:if>-->
  <xsl:text>','</xsl:text>-->
  <xsl:call-template name="escape-apos">
    <xsl:with-param name="string" select=".//ns2:Name" />
  </xsl:call-template>
  <xsl:text>','</xsl:text>
  <xsl:text>');</xsl:text>
</xsl:for-each>

Any help will be appreciated!

2 Answers 2

1

The good thing about your (american) date values is that they can be compared numerically without the - chars. So removing them enables a numeric comparison.
I also added some missing namespaces to your XML file and the XSLT to make the answer complete. Change the namespaces as you like - but equally in XML and XSLT.

XML:

<?xml version="1.0" encoding="UTF-8"?>
<ns3:ExportMedicines xmlns:ns2="http://ns2.com" xmlns:ns3="http://ns3.com">
  <ns3:Jkm code="35897">
    <ns3:Data from="2016-10-01" to="2020-07-21">
      <ns2:Name>
        <Fr>estradiol 1 mg comp + estradiol 1 mg + dydrogestérone 10 mg comp</Fr> 
      </ns2:Name>
    </ns3:Data>
    <ns3:Data from="2020-07-22">
      <ns2:Name>
        <Fr>estradiol 2 mg comp+ estradiol 1 mg + dydrogestérone 10 mg comp</Fr>
      </ns2:Name>
  </ns3:Data>
  </ns3:Jkm>
</ns3:ExportMedicines>

XSLT-1.0:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"  xmlns:ns2="http://ns2.com" xmlns:ns3="http://ns3.com">
<xsl:output method="xml" omit-xml-declaration="yes" />
<xsl:strip-space elements="*" />  
    
    <xsl:template match="/ns3:ExportMedicines">
        <xsl:for-each select="ns3:Jkm">
            <xsl:text>INSERT INTO JKM VALUES ('</xsl:text>
            <xsl:value-of select="@code" />
            <xsl:text>','</xsl:text>
            <xsl:for-each select="ns3:Data">
                <xsl:sort select="translate(@from,'-','')" order="descending" data-type="number" />
                <xsl:if test="position() = 1">
                    <xsl:call-template name="escape-apos">
                        <xsl:with-param name="string" select="ns2:Name" />
                    </xsl:call-template>
                </xsl:if>
                <xsl:text>','</xsl:text>
            </xsl:for-each>
            <xsl:text>','</xsl:text>
            <xsl:text>','</xsl:text>
            <xsl:text>');</xsl:text>
        </xsl:for-each>
    </xsl:template>
    
</xsl:stylesheet>

Output is (the newest):

INSERT INTO JKM VALUES ('35897','estradiol 2 mg comp+ estradiol 1 mg + dydrogestérone 10 mg comp','','','','');

This solution assumes that there is no overlapping between the to and the follwoing from value.

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

4 Comments

"they can be compared numerically" But you are sorting alphabetically. And for this, there is no need to remove the - characters.
Thank. I added the data-type="number attribute to explicitly indicate that it's a number though the result will be the same.
"the result will be the same" Right, so why bother. -- BTW: todayifoundout.com/index.php/2014/10/…
I thought I wrote explicitly in my first sentence that american dates (YYYY/MM/DD) can be compared this way. The TO used this format.
1

IIUC, you want to do:

    <xsl:for-each select="ns3:Jkm">
        <!-- omitted -->
        <xsl:value-of select="ns3:Data[not(@to)]/ns2:Name/Fr" /> 
        <!-- omitted -->
    </xsl:for-each>

This gets the value from the Data that does not have a to attribute - which I believe means it is current.


I'm using xsl 1.0 so as i already read i can't test date attributes.

You are mistaken about that. Your dates are in the YYYY-MM-DD format - which means they can be used for sorting alphabetically as they are, with no modification necessary.

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.