'xmlParseEntityRef: sem nome' avisos ao carregar xml em um arquivo php


91

Estou lendo um xml em php usando simplexml_load_file. No entanto, ao tentar carregar o xml, ele exibe uma lista de avisos

Warning: simplexml_load_file() [function.simplexml-load-file]: <project orderno="6" campaign_name="International Relief & Development" project in /home/bluecard1/public_html/test.php on line 3    
Warning: simplexml_load_file() [function.simplexml-load-file]: ^ in /home/bluecard1/public_html/test.php on line 3    
Warning: simplexml_load_file() [function.simplexml-load-file]: http://..../index.php/site/projects/:15: parser error : xmlParseEntityRef: no name in /home/bluecard1/public_html/test.php on line 3

Warning: simplexml_load_file() [function.simplexml-load-file]: ional Relief & Development" project_id="313" client_name="International Relief & in /home/bluecard1/public_html/test.php on line 3    
Warning: simplexml_load_file() [function.simplexml-load-file]: ^ in /home/bluecard1/public_html/test.php on line 3    
Warning: simplexml_load_file() [function.simplexml-load-file]: http://..../index.php/site/projects/:15: parser error : xmlParseEntityRef: no name in /home/bluecard1/public_html/test.php on line 3

Como retifico para remover esses avisos?

(XML é gerado a partir de url http://..../index.php/site/projectse carregado em uma variável no test.php. Não tenho privilégios de gravação para index.php)


O XML é inválido. Você pode não conseguir carregá-lo. Os erros podem ser suprimidos adicionando @antes simplexml_load_fileou adicionando um sinalizador, consulte a página de manual de simplexml_load_filepara mais informações e exclua sua pergunta, é uma duplicata.
hakre

Posso ver que minha resposta está recebendo bastante atenção, se essa for realmente a solução: você pode sinalizá-la como "resposta correta"? obrigado.
ricricucit

Respostas:


146

O XML é provavelmente inválido.

O problema pode ser o "&"

$text=preg_replace('/&(?!#?[a-z0-9]+;)/', '&amp;', $text);

irá livrar-se do "&" e substituí-lo pela sua versão de código HTML ... experimente.


2
Obrigado. Você salvou meu dia!
Saim,

2
A prática recomendada ao trabalhar com XML é garantir que não haja caracteres conflitantes e você deve substituí-los antes de parsin
Sr. Megamind

2
obrigado, o ponto principal desta questão é porque o xml é inválido
yussan,

Apenas um pequeno acréscimo, se você quiser substituir todos os "e" comerciais, anexe 'g' ao seu regex. A solução atualizada ficaria assim: $text=preg_replace('/&(?!#?[a-z0-9]+;)/g', '&amp;', $text);
flaming.codes

81

Encontrei isso aqui ...

Problema: um analisador XML retorna o erro “xmlParseEntityRef: noname”

Explicação: Há um '&' (caractere e comercial) perdido em algum lugar do texto XML, por exemplo. algum texto e mais algum texto

Solução:

  • Solução 1: Remova o E comercial.
  • Solução 2: codifique o e comercial (ou seja, substitua o &caractere por&amp; ). Lembre-se de decodificar ao ler o texto XML.
  • Solução 3: Use seções CDATA (o texto dentro de uma seção CDATA será ignorado pelo analisador). <! [CDATA [algum texto e mais algum texto]]>

Nota: '&' '<' '>' todos darão problemas se não forem tratados corretamente.


Nós sabemos por que isso acontece? Além disso, uma seção CDATA ainda será selecionada por um navegador que renderizaria alguns desses dados? Eu tenho algumas tags HTML dentro de minhas tags XML e preciso que sejam processadas para o usuário final para uma ferramenta de edição.
sulimmesh

11

Tente limpar o HTML primeiro usando esta função:

$html = htmlspecialchars($html);

Os caracteres especiais geralmente são representados de forma diferente em HTML e podem ser confusos para o compilador. Como &se torna &amp;.


Alguém pode explicar por que isso foi rejeitado? htmlspecialchars()é a função precisa para converter &, ", <, >chars nos dados do elemento.
JacobRossDev

7
Esta resposta foi rejeitada porque não funciona bem neste caso. Usar essa função quebrará totalmente seu XML ao converter "<" em "& lt;". Não tenho conhecimento de nenhuma maneira que você possa usar htmlspecialchars()e não quebrar XML. Tentei alguns sinalizadores e meu XML ainda quebrou.
Alex Finnarn

1
Você deve usar htmlspecialcharsno conteúdo de uma tag xml, não em todo o XML
gbalduzzi

7

Eu uso uma versão combinada:

strip_tags(preg_replace("/&(?!#?[a-z0-9]+;)/", "&amp;",$textorhtml))

1
Este está funcionando perfeitamente. Você está perdendo o colchete direito final
myh34d

7

PROBLEMA

  • A função PHP simplexml_load_fileestá gerando um erro de análise parser error : xmlParseEntityRefao tentar carregar o arquivo XML de um URL.

CAUSA

  • O XML retornado pelo URL não é um XML válido. Ele contém &valor em vez de &amp;. É bem possível que existam outros erros que não sejam óbvios neste momento.

COISAS FORA DE NOSSO CONTROLE

  • Idealmente, devemos ter certeza de que um XML válido é alimentado na simplexml_load_filefunção PHP , mas parece que não temos nenhum controle sobre como o XML é criado.
  • Também não é possível forçar o simplexml_load_fileprocessamento de um arquivo XML inválido. Isso não nos deixa com muitas opções, além de corrigir o próprio arquivo XML.

SOLUÇÃO POSSÍVEL

Converter XML inválido em XML válido. Isso pode ser feito usando PHP tidy extension. Mais instruções podem ser encontradas em http://php.net/manual/en/book.tidy.php

Assim que tiver certeza de que a extensão existe ou está instalada, faça o seguinte.

/**
 * As per the question asked, the URL is loaded into a variable first, 
 * which we can assume to be $xml
 */
$xml = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<project orderno="6" campaign_name="International Relief & Development for under developed nations">
    <invalid-data>Some other data containing & in it</invalid-data>
    <unclosed-tag>
</project>
XML;

/**
 * Whenever we use tidy it is best to pass some configuration options 
 * similar to $tidyConfig. In this particular case we are making sure that
 * tidy understands that our input and output is XML.
 */
$tidyConfig = array (
    'indent' => true,
    'input-xml' => true, 
    'output-xml' => true,
    'wrap' => 200
);

/**
 * Now we can use tidy to parse the string and then repair it.
 */
$tidy = new tidy;
$tidy->parseString($xml, $tidyConfig, 'utf8');
$tidy->cleanRepair();

/**
 * If we try to output the repaired XML string by echoing $tidy it should look like. 

 <?xml version="1.0" encoding="utf-8"?>
 <project orderno="6" campaign_name="International Relief &amp; Development for under developed nations">
      <invalid-data>Some other data containing &amp; in it</invalid-data>
      <unclosed-tag></unclosed-tag>
 </project> 

 * As you can see that & is now fixed in campaign_name attribute 
 * and also with-in invalid-data element. You can also see that the   
 * <unclosed-tag> which didn't had a close tag, has been fixed too.
 */
echo $tidy;

/**
 * Now when we try to use simplexml_load_string to load the clean XML. When we
 * try to print_r it should look something like below.

 SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [orderno] => 6
            [campaign_name] => International Relief & Development for under developed nations
        )

    [invalid-data] => Some other data containing & in it
    [unclosed-tag] => SimpleXMLElement Object
        (
        )

)

 */
 $simpleXmlElement = simplexml_load_string($tidy);
 print_r($simpleXmlElement);

CUIDADO

O desenvolvedor deve tentar comparar o XML inválido com um XML válido (gerado pelo tidy), para ver que não há efeitos colaterais adversos após o uso do tidy. O Tidy faz um trabalho extremamente bom em fazer isso corretamente, mas nunca é demais ver visualmente e ter 100% de certeza. Em nosso caso, deve ser tão simples quanto comparar $ xml com $ tidy.


6

O XML é inválido.

<![CDATA[ 
{INVALID XML}
]]> 

CDATA deve envolver todos os caracteres XML especiais, de acordo com W3C



1

Isso resolve meu problema:

$description = strip_tags($value['Description']);
$description=preg_replace('/&(?!#?[a-z0-9]+;)/', '&amp;', $description);
$description= preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $description);
$description=str_replace(' & ', ' &amp; ', html_entity_decode((htmlspecialchars_decode($description))));

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.