Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: MattОтветов: 1

Я использую 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"/> звучит как то, что мне нужно, но мне придется поэкспериментировать и посмотреть, как выглядят отсылки к персонажам на другом конце. Это может быть хорошим вариантом.

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

xmlplaintext

Ответы

Ответ 1 · рейтинг 1 · Martin Honnen

Вы на самом деле не объяснили, как вы хотите обрабатывать буквы, отличные от 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.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы