Могу ли я указать ограниченный набор символов для вывода XSL?

Я использую XSL для преобразования XML UTF-8 в открытый текст, и он предназначен только для систем ASCII. Мейнфрейм, среди прочего. Есть целый набор символов, которые потенциально могут быть в XML, что задушит нижестоящие системы. Целью существования этого XSL является обслуживание этих нижестоящих систем, поэтому я обязан предоставить им пригодные для использования файлы.

У меня есть МНОГО разных XSL, которые делают это.

Я исправил некоторые из критических XSL, чтобы использовать translate() для замены некоторых определенных символов, которые, как я знал, встречались и вызывали трудности, но только в качестве временной меры. Я не могу позволить себе сделать это для каждого символа в расширенном наборе, для каждого поля в каждом XSL, который я запускаю.

У меня нет никакого контроля над кодировкой или набором символов XML. Есть ли способ, которым я могу просто программно заставить XSL использовать только символы ASCII в создаваемом им текстовом файле? Какая-то спецификация в объявлении вывода?

РЕДАКТИРОВАТЬ: Чтобы быть более точным, важно, чтобы я не удалял никаких символов. Как и сейчас, с translate() мне нужно заменить символы, отличные от ASCII, на удобочитаемые альтернативы. В идеале существует способ указать XSL использовать какой-либо стандартизированный метод для замены не-ASCII-символов на ASCII-символы.

Во-вторых, я не могу выбросить никаких ошибок. Я не имею никакого контроля над отправляющей системой, поэтому, если есть какие-либо ошибки, я не могу сказать: «Эй, эта запись не удалась, пожалуйста, отправьте ее еще раз, используя только символы ASCII».

В-третьих, у меня есть некоторый контроль над процессом, поэтому я мог бы добавить дополнительный XSL, который просто переводит символы перед их передачей. Это неплохая идея, потому что мне нужно будет поддерживать только одно дополнительное преобразование. Однако мне нужно поддерживать почти 100 преобразований, поэтому мне придется изменить почти все их конвейеры. На самом деле это может быть хорошей альтернативой, если в XSL нет простого способа.

Идея <xsl:output encoding="US-ASCII"/> звучит как то, что мне нужно, но мне придется поэкспериментировать и посмотреть, как выглядят отсылки к персонажам на другом конце. Это может быть хорошим вариантом.


person Matt    schedule 12.01.2018    source источник
comment
Ну, есть <xsl:output encoding="US-ASCII"/>, см. w3.org/TR/xslt- xquery-serialization-31/#XML_ENCODING для того, что он делает, если у вас есть имя элемента, содержащее символ, отличный от ASCII, вы получите сообщение об ошибке, если у вас есть данные, содержащие символ, отличный от ASCII, этот символ будет выводиться как ссылка на персонажа.   -  person Martin Honnen    schedule 13.01.2018
comment
Если метод вывода text, то в соответствии с w3.org/TR/ xslt-xquery-serialization-31/#TEXT_ENCODING вы получите сообщение об ошибке для данных, отличных от ASCII, если вы выберете encoding="US-ASCII".   -  person Martin Honnen    schedule 13.01.2018
comment
Приемлемы ли ссылки на сущности персонажей, на которые ссылается @MartinHonnen? Или даже лучше, чем то, что ты делаешь сейчас?   -  person Tom Blodget    schedule 13.01.2018
comment
Не могли бы вы запустить два XSLT, первый для преобразования всех значений text(), а второй для форматирования XML в текст? В любом случае XSL может быть не лучшим инструментом для такого преобразования. (Если бы мне пришлось, я бы использовал свой msxsl:script Hammer.) Можете ли вы вставить в конвейер еще один процесс для фильтрации или транслитерации символов после шага XSL?   -  person Tom Blodget    schedule 13.01.2018
comment
К сожалению, XSL — мой единственный вариант. Я бы предпочел иметь дело почти с чем-то другим.   -  person Matt    schedule 15.01.2018


Ответы (1)


Вы на самом деле не объяснили, как вы хотите обрабатывать буквы, отличные от ASCII, но поскольку вы пометили вопрос как xslt-2.0 у вас есть доступ к регулярным выражениям XPath/XSLT 2.0, поэтому, например, для удаления любых символов, отличных от ASCII, из любых текстовых узлов вы можете использовать replace :

  <xsl:template match="text()">
      <xsl:value-of select="replace(., '[^\r\n\t&#x0020;-&#x007E;]+', '')"/>
  </xsl:template>

Другой способ написать замену:

  <xsl:template match="text()">
      <xsl:value-of select="replace(., '\P{IsBasicLatin}+', '')"/>
  </xsl:template>

Существует также функция normalize-unicode https://www.w3.org/TR/xpath-functions/#func-normalize-unicode, если вы не хотите просто удалять все символы, отличные от ASCII.

person Martin Honnen    schedule 13.01.2018
comment
Это хорошая идея. Это очень похоже на то, что я делаю сейчас, но избавляет меня от необходимости указывать каждый символ и каждую замену. Единственный недостаток (как и в случае с translate()) заключается в том, что в некоторых случаях мне приходится очищать 150 или более элементов, прежде чем записывать их в текстовый файл. Много мест, где можно добавить replace() вызов. Кроме того, система, для которой я пишу, не поддерживает все функции XSL, иначе я бы написал xsl:function с replace или translate и просто использовал его для записи значений. - person Matt; 15.01.2018
comment
Если вы хотите удалить символы, отличные от ASCII, из всего текста во входных данных, то приведенный выше шаблон должен сделать это независимо от имени любого родительского или предкового элемента. Поэтому я не понимаю, зачем вам нужно использовать replace в 150 местах. Но вы не показали ни одной из ваших существующих трансформаций. Возможно, лучше задать новый вопрос о том, как упростить таблицу стилей. - person Martin Honnen; 15.01.2018
comment
Нет, я просто пропустил эту часть. Я все еще новичок в XSL, поэтому для меня не было очевидным, что это не обязательно должно быть для каждого элемента. - person Matt; 16.01.2018