XSLT: сравните буквы, используемые в качестве ключа группировки

Я хотел бы сгруппировать элементы по первой букве, но некоторые разные буквы следует считать равными: A и Ä (а также a и ä) должны быть одинаковыми.

Источник:

<root>
  <entry name="Aa" />
  <entry name="Ab" />
  <entry name="Äa" />
  <entry name="Ac" />
  <entry name="Ba" />
</root>

Преобразование:

<xsl:stylesheet version="2.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
  <xsl:output indent="yes"/>

  <xsl:template match="root">
    <root>
      <xsl:for-each-group select="entry" group-by="upper-case(substring(@name,1,1))">
        <key><xsl:value-of select="current-grouping-key()"/></key>
      </xsl:for-each-group>
    </root>
  </xsl:template>

</xsl:stylesheet>

Результат сейчас:

<root>
   <key>A</key>
   <key>Ä</key>
   <key>B</key>
</root>

Результат такой, какой хотелось бы:

<root>
   <key>A</key>
   <key>B</key>
</root>

Где все записи, кроме «Bb», должны быть в первой группе.

Я предполагаю, что ключ к успеху - это сделать функцию group-by() правильной для обработки a, A, ä и Ä равными (это верно для некоторых немецких правил сортировки / упорядочения). Но я не нашел функции xpath, которая могла бы справиться с этим.


person topskip    schedule 16.05.2012    source источник
comment
Я нашел одно решение, но есть ли более умное / чистое? substring(normalize-unicode(upper-case(@name),'NFD'),1,1)   -  person topskip    schedule 16.05.2012


Ответы (2)


Как насчет translate(substring(@name,1,1), 'Ä', 'A')?

person xiaoyi    schedule 16.05.2012
comment
Выглядит неплохо, но должно быть более простое решение без дополнительных классов символов (Ü- ›U и Ö-› O и ß - ›s) - person topskip; 16.05.2012
comment
@ Патрик: просто сложи их вместе, как translate(substring(@name,1,1), 'ÄßÜÖ', 'ASUO') - person xiaoyi; 16.05.2012
comment
Стыдно, мне следовало заглянуть в документацию. Вы, конечно, правы. Большое спасибо! - person topskip; 16.05.2012

Есть два возможных подхода:

(a) использовать атрибут сопоставления xsl: for-each-group, указывая сопоставление, которое имеет правильную семантику сравнения. К сожалению, это будет зависеть от вашего XSLT-процессора. Например, для Saxon вы можете использовать

http://saxon.sf.net/collation?lang=de;ignore-case=yes;ignore-modifiers=yes

как описано здесь:

http://www.saxonica.com/documentation/extensibility/collation.xml

(б) альтернативой является «сделай сам», как рекомендуют большинство ответов здесь: то есть напишите некоторую функцию, которая нормализует регистр и удаляет акценты, прежде чем выполнять группировку. Вызов нижнего регистра () или верхнего регистра () не идеален для нормализации регистра, хотя верхний регистр (), вероятно, подходит для немецкого языка, где основная проблема состоит в том, чтобы объединить группы «ß» и «ss». Избавиться от акцентов можно, используя normalize-unicode () для нормализации до разложенной нормальной формы Unicode, а затем replace () для удаления символов из категории \ p {Lm}.

Я бы рекомендовал использовать сопоставления.

person Michael Kay    schedule 16.05.2012