Получить значение узла, если атрибут не существует

#xml #xslt

#xml #xslt

Вопрос:

У меня есть XML-файл, который содержит несколько элементов с одинаковыми именами, но разными атрибутами.

 <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>
  

Я хотел бы получить более свежий <ns3:data> элемент.
Я использую xsl 1.0, поэтому, поскольку я уже прочитал, я не могу проверить атрибуты даты.
Итак, я думаю, что один из способов сделать это — проверить, не существует ли атрибут to .

Я не могу использовать template match , потому что я уже в for-each

Вот фрагмент из моего 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>
  

Любая помощь будет оценена!

Ответ №1:

Хорошая вещь в ваших (американских) значениях даты заключается в том, что их можно сравнивать численно без - символов. Таким образом, их удаление позволяет проводить числовое сравнение.
Я также добавил некоторые недостающие пространства имен в ваш XML-файл и XSLT, чтобы сделать ответ полным. Измените пространства имен по своему усмотрению — но одинаково в XML и 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>
  

Вывод (самый новый):

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

Это решение предполагает, что между to и следующим from значением нет перекрытия.

Комментарии:

1. «их можно сравнить численно» Но вы сортируете в алфавитном порядке. И для этого нет необходимости удалять - символы.

2. Спасибо. Я добавил data-type="number атрибут, чтобы явно указать, что это число, хотя результат будет тем же самым.

3. «результат будет тем же» Верно, так зачем беспокоиться. — КСТАТИ: todayifoundout.com/index.php/2014/10 /…

4. Я думал, что в своем первом предложении я явно написал, что американские даты (ГГГГ / ММ / ДД) можно сравнить таким образом. В TO использовался этот формат.

Ответ №2:

IIUC, вы хотите сделать:

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

Это возвращает значение из того, у Data которого нет to атрибута, что, я полагаю, означает, что оно текущее.


Я использую xsl 1.0, поэтому, поскольку я уже прочитал, я не могу проверить атрибуты даты.

Вы ошибаетесь на этот счет. Ваши даты приведены в формате ГГГГ-ММ-ДД, что означает, что их можно использовать для сортировки в алфавитном порядке, как они есть, без необходимости внесения изменений.