Подсчет XML на основе условных обозначений даты с помощью xslt

С xslt работаю впервые. У меня 2.0, но это единственное преимущество, к которому у меня есть доступ к имеющейся у нас библиотеке преобразования C #. Я пытаюсь подсчитать количество дочерних узлов в XML-документе, которые содержат дату более 12 лет назад и имеют определенный атрибут типа.

Пример структуры xml:

<xml version=\"1.0\" encoding=\"utf-8\"?>
<... />
<Dependents>
<Dependent><DOB>1964-04-01</DOB><DependentType>Spouse</DependentType></Dependent>
<Dependent><DOB>2000-01-01</DOB><DependentType>Child</DependentType></Dependent>
<Dependent><DOB>2012-01-01</DOB><DependentType>Child</DependentType></Dependent>
</Dependents>
<... />

где <... /> означает дополнительные несвязанные вещи.

По сути, мне нужно количество детей младше 12 лет. (У меня есть количество работающих детей в возрасте до 12 лет, с которыми у меня работают, у меня есть проблемы с детьми младше 12 лет). Подход, который мне предложили, состоял в том, чтобы создать переменную, которая существует 12 лет назад с сегодняшнего дня, и использовать ее в качестве основы для сравнения в функции count(). Это звучит разумно, но я застрял в построении даты без использования сторонних библиотек (например, exslt), которые так часто связаны в подобных вопросах для получения простых и удобных ответов.

Вот xslt, который я получил за это:

<xsl:variable name="today" select="current-dateTime()" as="xs:dateTime" />
<xsl:variable name="twelveyearsago" select="xs:dateTime(concat(year-from-dateTime($today) - 12, '-', month-from-dateTime($today), '-', day-from-dateTime($today)))" />
<xsl:text>12yearsago=</xsl:text><xsl:value-of select="$twelveyearsago" />

И это не работает, потому что в поле month-from-dateTime (и предположительно day-from-dateTime) не добавляются начальные нули. На сегодня, 21 марта 2012 г., я возвращаюсь: Saxon.Api.DynamicError: Недействительное значение dateTime "2000-3-21" (месяц должен быть двухзначным) (Ссылка на функцию xpath W3Schools подразумевает, что они должны, но это не так.)

Я хотел бы вывести:

<xsl:text>&amp;numberofchildren=</xsl:text><xsl:value-of select="count(//InsuranceRequest/HealthInsurance/Dependents/Dependent/DependentType[text() = 'Child'])" />
<xsl:text>&amp;childrenunder12=</xsl:text><xsl:value-of select="children under twelve" />

Чем больше я бьюсь об это головой, тем больше чувствую, что есть более простой подход, которого я просто не вижу.

Изменить: я очистил синтаксис xslt, поэтому он действителен, а не является строкой С # с двойными кавычками.


person Patrick M    schedule 21.03.2012    source источник


Ответы (1)


Вы можете просто вычесть продолжительность из 12 лет, как в <xsl:variable name="twelveyearsago" select="$today - xs:yearMonthDuration('P12Y')"/>, затем использовать, например, //Dependent[DependentType = 'Child' and xs:date(DOB) >= $twelveyearsago].

[править] Вот шаблон, который компилируется и отлично работает с Saxon 9.4:

  <xsl:template match="/">
    <xsl:variable name="today" select="current-date()"/>
    <xsl:variable name="twelve-years-ago" select="$today - xs:yearMonthDuration('P12Y')"/>
    <xsl:value-of select="count(//Dependent[DependentType = 'Child' and xs:date(DOB) >= $twelve-years-ago])"/>
  </xsl:template>
person Martin Honnen    schedule 21.03.2012
comment
yearMonthDuration работает нормально, хотя, клянусь, раньше он не работал ... Без сомнения, глупая синтаксическая ошибка с моей стороны. Однако я не думаю, что DependedType = 'Child' правильно, я думаю, что нужно как-то ссылаться на text (). По крайней мере, не работает так, как вы написали. Сейчас я пробую кое-что, но я буду благодарен за любые подсказки. - person Patrick M; 21.03.2012
comment
Если хотите, можете использовать //Dependent[DependentType/text() = 'Child'], но то, что я предложил, достаточно и, на мой взгляд, используется чаще. Явный выбор текстовых узлов требуется только при работе со смешанным содержимым. Если у вас все еще есть проблемы с тем, чтобы что-то работало, опубликуйте минимальные, но полные, а также полезные образцы кода, тогда я уверен, что мы сможем это исправить. Но я не в настроении пытаться преобразовывать ваши строки C # в XML-документы только для того, чтобы убедить вас, что DependentType = 'Child' является рабочим кодом. Единственная проблема, которую я вижу, - это ваш DependedType = 'Child', в котором опечатка или неправильное имя. - person Martin Honnen; 21.03.2012
comment
Вы были правы, что это count(//Dependents/Dependent[DependentType = 'Child'] работает. Но я не могу заставить это count(//Dependents/Dependent[xs:date(DOB) >= $twelveyearsago]) работать. Извините за опечатку. - person Patrick M; 21.03.2012
comment
Извините за это, я думаю, вы получаете ошибку, которую вы не можете сравнить xs:date с xs:dateTime. Самый простой способ исправить это - использовать current-date() вместо current-dateTime() для переменной today. Я отредактирую свой пост с помощью образца, который я тестировал с Saxon. - person Martin Honnen; 21.03.2012
comment
Ага, это сработало. Я только что обнаружил это и пытался превратить DOB в dateTime вместо гораздо более простого исправления, которое вы предложили. Также обнаружил, что мы используем Saxon 9.2, и я пытался выяснить, где он сбрасывает точные ошибки. В любом случае, большое спасибо! - person Patrick M; 21.03.2012