Как я могу избежать текста для XML-документа в Perl?

Кто-нибудь знает какой-нибудь модуль Perl для экранирования текста в XML-документе?

Я генерирую XML, который будет содержать текст, введенный пользователем. Я хочу правильно обрабатывать текст, чтобы получаемый XML был правильно сформирован.

8 ответов

Решение

Я лично предпочитаю XML:: LibXML - связывание Perl для libxml. Один из плюсов - он использует одну из самых быстрых доступных библиотек обработки XML. Вот пример для создания текстового узла:

use XML::LibXML;
my $doc = XML::LibXML::Document->new('1.0',$some_encoding);
my $element = $doc->createElement($name);
$element->appendText($text);
$xml_fragment = $element->toString();
$xml_document = $doc->toString();

И никогда не создавайте XML вручную. Это будет плохо для вашего здоровья, когда люди узнают, что вы сделали.

Можно также использовать XML::Simple escape_value, но использование XML:: Simple не рекомендуется для новых программ. Смотрите этот пост пост 17436965.

Экранирование вручную может быть выполнено с помощью регулярного выражения (скопировано из escape_value):

$data =~ s/&/&/sg;
$data =~ s/</&lt;/sg;
$data =~ s/>/&gt;/sg;
$data =~ s/"/&quot;/sg;

Я не уверен, почему вам нужно экранировать текст, который находится в файле XML. Если ваш файл содержит:

<foo>x < y</foo>

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

<foo>x &lt; y</foo>

или же

<foo><![CDATA[x < y]]></foo>

Поэтому либо:

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

  2. У вас есть некоторые данные в файле XML, которые необходимо экранировать по какой-либо другой причине.

Хотите разработать?

Используйте XML:: Code.

Из CPAN

XML:: код escape()

Обычно любое содержимое узла будет экранировано во время рендеринга (т. Е. Специальные символы, такие как '&', будут заменены соответствующими объектами). Вызвать escape() с нулевым аргументом, чтобы предотвратить это:

        my $p = XML::Code->('p');
        $p->set_text ("&#8212;");
        $p->escape (0);
        print $p->code(); # prints <p>&#8212;</p>
        $p->escape (1);
        print $p->code(); # prints <p>&amp;#8212;</p>

Использование

XML::Generator

требуют XML::Generator;

my $ xml = XML::Generator-> new (': pretty', escape => 'всегда, apos');

print $ xml-> h1 ("& <> обычный текст без HTML < >&");

который будет печатать весь контент внутри экранированных тегов (не конфликтует с разметкой).

XML:: Entities:

use XML::Entities;
my $a_encoded = XML::Entities::numify('all', $a);

Редактировать: XML::Entities только нумерует HTML-сущности. Вместо этого используйте HTML:: Entities encode_entities ($ a)

После проверки XML::Code в соответствии с рекомендациями Krish я обнаружил, что это можно сделать с помощью XML::Code text() функция. Например,

use XML::Code;
my $text = new XML::Code('=');
$text->set_text(q{> & < " ' "});
print $text->code(); # prints &gt; &lt; &amp; " ' "

Передача '=' создает текстовый узел, который при печати не содержит тегов.Примечание: это работает только для текстовых данных. Это не будет правильно избегать атрибутов.

For programs that need to handle every special case, by all means use an official library for this task. However, theoretically there are only 5 characters that need escaping in XML.

So, for one-offs that you don't want to pull in an extra library for, the following perl expression should suffice:

perl -pe 's/\&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g; s/"/\&quot;/g; s/'"'"'/\&apos;/g'

Хотя лучше использовать такой модуль, как XML::LibXML или же XML::Code Вы можете обернуть текстовые данные в разделе CDATA. Вы должны только заботиться, чтобы не положить ]]> в нем (эта последовательность также запрещена за пределами разделов CDATA!):

$text =~ s/\]\]>/]]>]]&gt;<![CDATA[/;
$text = "<![CDATA[$text]]>";
$xml = "<foo>$text</foo>"; 

В качестве бонуса ваш код будет выглядеть более запутанным!:-)

Другие вопросы по тегам