Как я могу разделить недопустимые символы XML от строк в Perl?

Актуальная проблема того, почему это не работает, описана здесь , ,

.

Тем не менее, данное решение для создания метателя броска для прохождения проверки не будет работать в вашем случае.

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

10
задан brian d foy 19 June 2009 в 18:42
поделиться

9 ответов

Полное регулярное выражение для удаления недопустимых символов xml-1.0:

# #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
$str =~ s/[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go;

для xml-1.1 это:

# allowed: [#x1-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
$str =~ s/[^\x01-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go;
# restricted:[#x1-#x8][#xB-#xC][#xE-#x1F][#x7F-#x84][#x86-#x9F]
$str =~    s/[\x01-\x08\x0B-\x0C\x0E-\x1F\x7F-\x84\x86-\x9F]//go;
7
ответ дан 3 December 2019 в 15:36
поделиться

Как уже говорили почти все, используйте регулярное выражение. Честно говоря, это недостаточно сложно, чтобы его стоило добавить в библиотеку. Предварительно обработайте текст подстановкой.

Ваш комментарий о переводе строки выше предполагает, что форматирование имеет для вас некоторое значение, поэтому вам, возможно, придется точно решить, чем вы хотите заменить некоторые символы.

Список недопустимых символов четко определен в спецификации XML (здесь - http://www.w3.org/TR/REC-xml/#charsets - например). Запрещенные символы - это управляющие символы ASCII в виде строки возврата каретки, перевода строки и табуляции. Итак, перед вами 29 символьный класс символов регулярного выражения. Это, конечно, не так уж и плохо.

Что-то вроде:

$text =~ s/[\x00-\x08 \x0B \x0C \x0E-\x19]//g;

должно это сделать.

6
ответ дан 3 December 2019 в 15:36
поделиться

Translate - это лот быстрее, чем подстановка регулярного выражения. Особенно, если вы хотите удалить все символы. Использование набора newt:

$string_to_clean =~ tr/\x00-\x08\x0B\x0C\x0E-\x19//d;

Пример такого теста:

cmpthese 1_000_000
       , { translate => sub { 
               my $copy = $text; 
               $copy =~ tr/\x00-\x08\x0B\x0C\x0E-\x19//d; 
           }
           , substitute => sub { 
               my $copy = $text; 
               $copy =~ s/[\x00-\x08\x0B\x0C\x0E-\x19]//g; 
           }
         };

yeilded:

                Rate substitute  translate
substitute  287770/s         --       -86%
translate  2040816/s       609%         --

И чем больше символов мне нужно для удаления, тем быстрее получается отношение tr.

4
ответ дан 3 December 2019 в 15:36
поделиться

Хорошо, кажется, на этот вопрос уже дан ответ, но какого черта. Если вы хотите создавать XML-документы, вы должны использовать XML-библиотеку.

#!/usr/bin/perl
use strict;
use XML::LibXML;

my $doc = XML::LibXML::Document->createDocument('1.0');
$doc->setURI('http://example.com/myuri');
$doc->setDocumentElement($doc->createElement('root-node'));

$doc->documentElement->appendTextChild('text-node',<<EOT);
    This node contains &, ñ, á, <, >...
EOT

print $doc->toString;

Это дает следующее:

$ perl test.pl
<?xml version="1.0"?>
<root-node><text-node>    This node contains &amp;, &#x6C821;, &lt;, &gt;...
</text-node></root-node>

Изменить: Теперь я вижу, что вы уже используете XML :: LibXML.

3
ответ дан 3 December 2019 в 15:36
поделиться

Вы можете использовать регулярное выражение для удаления управляющих символов, например, \ cH будет соответствовать \ cL или \ x08 и \ x0C, оба будут соответствовать Backspace и Formfeed соответственно.

0
ответ дан 3 December 2019 в 15:36
поделиться

Вы можете использовать простое регулярное выражение , чтобы найти и заменить все управляющие символы в вашем фрагменте текста, заменяя их пробелом или удаляя их полностью-

# Replace all control characters with a space
$text =~ s/[[:cntrl:]]/ /g;

# or remove them
$text =~ s/[[:cntrl:]]//g;
0
ответ дан 3 December 2019 в 15:36
поделиться

Раньше я не много работал с XML, содержащим "недопустимые" символы, но Мне кажется, у вас здесь две совершенно разные проблемы.

Во-первых, в ваших данных есть символы, которые вам могут не понадобиться. Вы должны решить, что это такое и как вы хотите удалить / заменить их независимо от каких-либо ограничений XML. Например, у вас могут быть такие вещи, как x ^ H_y ^ H_z ^ H_ , где вы решаете удалить как пробел, так и следующий символ. Или возможно, что вы на самом деле не хотите корректировать свои данные, но чувствуете себя вынужденным из-за необходимости представить их в XML.

Обновление: я сохранил следующие абзацы для потомков, но они основаны на недоразумении : Я думал, что вы можете включить любой символ в данные XML, если вы правильно его закодируете, но, похоже, есть некоторые символы, которые прямо запрещены, даже закодировано? XML :: LibXML удаляет их (по крайней мере, в текущей версии), за исключением символа nul, который он рассматривает как конец строки, отбрасывая его и все, что следует за ним: (

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

use HTML::Entities "encode_entities_numeric";
$encoded_string = encode_entities_numeric( $string, "\x00-\x08\x0B\x0C\x0E-\x19");

Но на самом деле это всего лишь временная мера. Используйте правильный модуль XML; см., Например, этот ответ .

0
ответ дан 3 December 2019 в 15:36
поделиться

Если вы используете XML-библиотеку для создания своего XML (в отличие от конкатенации строк, простых шаблонов и т. Д.) , тогда он позаботится об этом за вас. Нет смысла изобретать колесо.

3
ответ дан 3 December 2019 в 15:36
поделиться

Я нашел решение, но оно использует команду iconv вместо perl.

$ iconv -c -f UTF-8 -t UTF-8 invalid.utf8 > valid.utf8

Приведенные выше решения, основанные на регулярных выражениях, не работают!!! , рассмотрим следующий пример:

$ perl -e 'print "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root>\x{A0}\x{A0}</root>"' > invalid.xml
$ perl -e 'use XML::Simple; XMLin("invalid.xml")'
invalid.xml:2: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0xA0 0xA0 0x3C 0x2F
$ perl -ne 's/[^\x09\x0A\x0D\x20-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]//go; print' invalid.xml > valid.xml
$ perl -e 'use XML::Simple; XMLin("valid.xml")'
invalid.xml:2: parser error : Input is not proper UTF-8, indicate encoding !
Bytes: 0xA0 0xA0 0x3C 0x2F

Фактически, два файла invalid.xml и valid.xml являются идентичными.

Дело в том, что диапазон "\x20-\x{D7FF}" соответствует валидным представлениям этих символов юникода, но не, например, невалидной последовательности символов "\x{A0}\x{A0}".

5
ответ дан 3 December 2019 в 15:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: