封装XML中的命名实体会导致解析错误

时间:2014-08-26 11:01:19

标签: xml perl named-entity-recognition

我的XML文档包含封装为CDATA的其他XML文档,如下所示:

    <mds>
      <md>
        <value>
          <![CDATA[<?xml version="1.0" encoding="UTF-8"?><record xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/">
             <dc:title>some text containing &amp;</dc:title></record>]]>
        </value>
      </md>
    </mds>

我使用LibXML从中提取此XML和dc:title:

$dcrawData = <get the CDATA from above>;
$dcDOM = $::PRSR->load_xml(expand_entities => 0, string => $dcRawData);
$dcTitle = $dcDOM->findvalue("//dc:title");

然后我通过执行字符串替换将其插入另一个XML部分:

<mods:titleInfo>
    <mods:title>some text containing &</mods:title>
</mods:titleInfo>

正如您所看到的,&amp; amp实体得到了扩展并成为单一&amp ;.这是一个问题,因为现在,生成的XML会生成解析错误,因为任何解析器都需要一个命名实体。

有没有办法在使用findvalue时阻止LibXML扩展命名实体或在使用值之前重新编码它们?其他记录中可能还有其他人。 expand_entities选项没有区别。

3 个答案:

答案 0 :(得分:2)

好的,我想我找到了解决方案。 XML::Entities将完成对字符串中实体进行重新编码的工作。

但是,我需要将编码的字符限制为少数,否则编码的字符串将包含xml解析器无法识别的实体。

所以目前我使用

$dcTitle = encode_entities($dcDOM->findvalue("//dc:title"),'&<>"');

仅编码&符号和一些特殊的xml字符。

答案 1 :(得分:1)

  

然后我通过执行字符串替换

将其插入另一个XML部分

别。如果您想将数据插入到XML文档中,那么您应该使用支持XML的知识API来处理任何必要的转义。

答案 2 :(得分:1)

  

然后我通过执行字符串替换

将其插入另一个XML部分

这是你做错的部分。您正在将文本插入XML而不将其转换为XML。 (这称为注入错误。)您需要转义&<以及文档字符集之外的任何字符。

sub text_to_xml {
   my ($s) = @_;
   for ($s) {
      s/&/&amp;/g;
      s/</&lt;/g;
      s/"/&quot;/g;  # So it can be used for attributes too
      s/'/&apos;/g;  # So it can be used for attributes too
   }
   return $s;
}

请勿忘记,您还需要根据文档的编码对其进行编码。