XSLT-заполнение символов для европейских символов для вывода с фиксированной шириной - PullRequest
2 голосов
/ 01 июля 2010

У меня есть требование взять немного XML и преобразовать его в файл загрузки фиксированной ширины для загрузки в систему SAP.Мой алгоритм работает отлично, за исключением некоторых странных европейских символов, таких как Ã, который, когда в строке возвращает длину строки +1 для каждого экземпляра символа.Так, например, текст Ãbcd будет иметь длину строки ($ value) 5 вместо 4.

Это проблема, потому что мой код проверяет, какова длина свойства, затем вычитает, чтоиз максимальной длины выходного формата фиксированной длины (т. е. для поля шириной 30, если он читает Ãbcd, он подумает, что ему нужно 25 пробелов вместо 26).сделать это, или что я делаю неправильно в моем алгоритме?

Ниже приведены мои шаблоны xsl (по большей части ... не могу получить их здесь совершенно правильно ...)

Шаблон для записи Свойство:

<xsl:param name="value"/>
<xsl:param name="width"/>

<!-- find the current length of the field-->
<xsl:variable name="valueWidth" select="string-length($value)" />
<xsl:variable name="difference" select="$width - $valueWidth" />


  <xsl:if test="$difference &gt; 0">
  <xsl:value-of select="$value"/>
  <!-- run this for loop x times outputing space for each -->
  <xsl:call-template name="for-loop-spaces">
    <xsl:with-param name="count" select="$difference - 1" />
  </xsl:call-template>

</xsl:if>


<xsl:if test="($difference &lt; 0)">
  <xsl:value-of select="substring($value,0,$width)"/>
</xsl:if>

<xsl:if test="$difference = 0">
  <xsl:value-of select="$value"/>
</xsl:if>
</xsl:template>

Шаблон For-loop-space (он не копирует-вставляет): выводит пробел при каждом вызове.принимает параметр "считать".Если count больше нуля, рекурсивно вызывайте с count-1 до 0.

Любой ввод будет очень полезным:)

Ответы [ 4 ]

2 голосов
/ 01 июля 2010

string-length(), как и все XSLT / XPath, основано на символах, а не на байтах, поэтому string-length("Ãbcd") обязательно должно дать 4. Если оно дает 5, то либо:

  • Ваш Ã на самом деле представляет собой два отдельных символа, один из которых представляет собой диакритический символ тильды, и это действительно правильно, даже если это означает, что столбцы визуально не выстраиваются.Но я думаю, что, вероятно, нет, так как версия, которую вы вставили здесь, представляет собой один составной символ, U + 00C3 LATIN CAPITAL LETTER A WITH TILDE.или

  • ваш входной XML был прочитан с использованием неправильной кодировки, фактически он находится в UTF-8 (по умолчанию для XML), но читался как-то еще, обычно ISO-8859-1, в результате чего символ U + 00C3, представленный последовательностью байтов 0xC3,0x83, выходит в виде двух символов U + 00C3, U + 0083 (Ã).

Это непросто «странные европейские символы», о которых вам нужно беспокоиться;если вы неправильно используете Unicode, то все символов вне основного 7-битного набора ASCII будут искажены, в том числе многие, которые даже замкнутые американцы любят использовать.

В любом случаевопрос о том, что SAP хочет для своего формата ввода FWV.Все это очень хорошо обрабатывает Ã как один символ и добавляет правильное количество символов заполнения для одного символа, но если вы затем выводите в UTF-8, а SAP на самом деле не читает UTF-8, это все равно нарушитimport.

Вам необходимо выяснить кодировку, ожидаемую целевой установкой SAP (если это не UTF-8, cp1252 - еще одна хорошая попытка), а также выяснить, является ли фиксированнаястолбцы формата основаны на символах Unicode или байтах.Из этого (связанного?) spec Я полагаю, что они на самом деле основаны на байтах, и в этом случае 5 будет на самом деле правильной длины байта, если ваша база данных должна содержать UTF-8.

К сожалению, XSLT полностью посвящен символам и не дает вам возможности работать с байтами, поэтому, если входной файл основан на байтах, вам придется либо:

  • удалитьвсе символы, не входящие в ASCII, ставящие спорными, или

  • используют другой инструмент вне XSLT для выполнения этой обработки, который знает о байтах.Честно говоря, для меня это имеет смысл: XSLT идеально подходит для преобразований XML в XML и в значительной степени ужасен для других задач обработки строк.Ваш шаблон выше можно сделать более читабельным и эффективным, переписав его за пару строк современного языка сценариев, такого как Python.

2 голосов
/ 01 июля 2010

Проблема заключается в том, что вместо одиночных символов можно использовать диакритические знаки. Это то, что дает вам «неправильную длину».

См. http://en.wikipedia.org/wiki/Combining_character для получения дополнительной информации об этих символах.

Если у вас есть XSLT 2, есть встроенная функция для их нормализации, которая должна работать: fn: normalize-unicode

Для XSLT 1.0 вам придется использовать некоторую функцию для подсчета символов, исключая комбинированные символы. Одной из возможностей может быть использование перевода:

translate($input, '&#768;&#769;&#770;&#771;&#772;&#773;&#774;&#775;&#776;&#777;&#778;&#779;&#780;&#781;&#782;&#783;&#784;&#785;&#786;&#787;&#788;&#789;&#790;&#791;&#792;&#793;&#794;&#795;&#796;&#797;&#798;&#799;&#800;&#801;&#802;&#803;&#804;&#805;&#806;&#807;&#808;&#809;&#810;&#811;&#812;&#813;&#814;&#815;&#816;&#817;&#818;&#819;&#820;&#821;&#822;&#823;&#824;&#825;&#826;&#827;&#828;&#829;&#830;&#831;&#832;&#833;&#834;&#835;&#836;&#837;&#838;&#839;&#840;&#841;&#842;&#843;&#844;&#845;&#846;&#847;&#848;&#849;&#850;&#851;&#852;&#853;&#854;&#855;&#856;&#857;&#858;&#859;&#860;&#861;&#862;&#863;&#864;&#865;&#866;&#867;&#868;&#869;&#870;&#871;&#872;&#873;&#874;&#875;&#876;&#877;&#878;&#879;', '')

Обратите внимание, что у вас будет еще больше проблем, если у вас есть азиатские символы, которые объединены.

Цитата из http://www.dpawson.co.uk/xsl/characters.html

Однако, если объединение Unicode символ используется и входной файл имеет е '(где' на самом деле сочетая острый характер) то пока предполагается любой рендерер с поддержкой Unicode чтобы сделать это острым для рендеринга, для движка XML это два символы е и острые.

0 голосов
/ 01 июля 2010

Вы считаете байты или символы? Ã, о котором вы упоминаете, - это 1 символ, но 2 байта (при использовании UTF-8, что, похоже, имеет место) Символы в UTF-8 могут занимать 1-4 байта.

Если длина строки считает байты, результат верный.

0 голосов
/ 01 июля 2010

Это не проблема XSLT, а, вероятно, проблема кодирования вывода.Как выполняется ваш XSLT?Возможно, вам придется изменить настройки модуля записи вывода.

Как отметил Одед, это может быть связано с кодировкой входного считывателя, а не выходной кодировки, как, согласно спецификации XPath, длина строки считает символы, так что вы можете считать символы строки, преобразованные в более чем один символ для Ä.Может быть, ввод UTF-8, но ваша конфигурация читает его как однобайтовую кодировку?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...