我正在尝试使用XMLReader读取大型XML文件,但是我找不到正确循环遍历子树的方法。
到目前为止,我尝试使用read()和next()函数。而且它不能正常工作。这是我正在解析的XML结构:
<CLIENTES>
<CLIENTE>
<CODIGO_INTERESSADO>10</CODIGO_INTERESSADO>
<NOME_INTERESSADO>Pedro</NOME_INTERESSADO>
<ENDERECO />
<COMPLEMENTO />
<ESTADO />
<MUNICIPIO />
<BAIRRO />
<CEP />
<DATA_CADASTRO>16/09/2015</DATA_CADASTRO>
<STATUS>Ativo</STATUS>
<TELEFONES>
<TELEFONE>
<NUMERO>(21) 96909-6905</NUMERO>
<TIPO>Celular</TIPO>
</TELEFONE>
</TELEFONES>
</CLIENTE>
<CLIENTE>
<CODIGO_INTERESSADO>11</CODIGO_INTERESSADO>
<NOME_INTERESSADO>Luiz</NOME_INTERESSADO>
<ENDERECO />
<COMPLEMENTO />
<ESTADO />
<MUNICIPIO />
<BAIRRO />
<CEP />
<DATA_CADASTRO>16/09/2015</DATA_CADASTRO>
<STATUS>Ativo</STATUS>
<TELEFONES>
<TELEFONE>
<NUMERO>(21) 96909-6901</NUMERO>
<TIPO>Celular</TIPO>
</TELEFONE>
</TELEFONES>
</CLIENTE>
</CLIENTES>
如您所见,节点TELEFONES可以具有多个TELEFONE节点。所以我需要循环播放并单独获取它们。到目前为止,这是我的代码:
$xml = new XMLReader();
$xml->open('xml_formatado_stack.xml');
$cont = 0;
$clientes = array();
while ($xml->read()) {
if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'CLIENTES') {
while ($xml->read()) {
if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'CLIENTE') {
while ($xml->read()) {
$telefone = array();
if($xml->nodeType == XMLReader::ELEMENT) {
if($xml->localName == 'CODIGO_INTERESSADO') {
$xml->read();
echo $xml->value."<br>";
$clientes[$cont]['codigo_interessado'] = $xml->value;
}
if($xml->localName == 'NOME_INTERESSADO') {
$xml->read();
$clientes[$cont]['nome_interessado'] = $xml->value;
}
if($xml->localName == 'ENDERECO') {
$xml->read();
$clientes[$cont]['endereco'] = $xml->value;
}
if($xml->localName == 'COMPLEMENTO') {
$xml->read();
$clientes[$cont]['complemento'] = $xml->value;
}
if($xml->localName == 'ESTADO') {
$xml->read();
$clientes[$cont]['estado'] = $xml->value;
}
if($xml->localName == 'MUNICIPIO') {
$xml->read();
$clientes[$cont]['municipio'] = $xml->value;
}
if($xml->localName == 'BAIRRO') {
$xml->read();
$clientes[$cont]['bairro'] = $xml->value;
}
if($xml->localName == 'CEP') {
$xml->read();
$clientes[$cont]['cep'] = $xml->value;
}
if($xml->localName == 'DATA_CADASTRO') {
$xml->read();
$clientes[$cont]['data_cadastro'] = $xml->value;
}
if($xml->localName == 'STATUS') {
$xml->read();
$clientes[$cont]['status'] = $xml->value;
}
if ($xml->localName == 'TELEFONES') {
while ($xml->read()) {
if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'TELEFONE') {
while ($xml->read()) {
if($xml->nodeType == XMLReader::ELEMENT) {
if($xml->localName == 'NUMERO') {
$xml->read();
$telefone['numero'] = $xml->value;
}
if($xml->localName == 'TIPO') {
$xml->read();
$telefone['tipo'] = $xml->value;
}
}
}
}
}
$clientes[$cont]['telefones'][] = $telefone;
$cont++;
}
}
}
}
}
}
}
var_dump($clientes);
$xml->close();
我在这里遇到两个问题。首先,我的最后一个数组仅包含有关一个CLIENTE节点的信息。它应该具有所有CLIENTE节点,我使用$ cont var为它们建立索引。
另一个问题是,去我的$ clientes数组的TELEFONES节点属于XML的最后一个CLIENTE节点。因此,我的代码以某种方式遍历每个CLIENTE节点,但是当我对待TELEFONES节点时,我的$ clientes数组变得一团糟。
我只是找不到使用XMLParser循环子树的方法。有人可以帮我吗?
答案 0 :(得分:0)
您可以使用XMLReader
要求它导入句段,而不是尝试逐元素读取整个文档。
在此示例代码中,一旦到达<CLIENTE>
级别,它将(使用simplexml_import_dom()
将该级别的所有元素读取到SimpleXMLElement中。完成此操作后,您就可以使用更简单的界面来处理每个人,而不必处理开始和结束标签等...
$xml = new XMLReader();
$xml->open('xml_formatado_stack.xml');
$clientes = array();
$doc = new DOMDocument;
while ($xml->read()) {
if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'CLIENTES') {
while ($xml->read()) {
if ($xml->nodeType == XMLReader::ELEMENT && $xml->localName == 'CLIENTE') {
// Import all child elements into $cl
$cl = simplexml_import_dom($doc->importNode($xml->expand(), true));
// Extract each piece of data, i.e. $cl->CODIGO_INTERESSADO and convert to string to store it
$cliente = [ 'codigo_interessado' => (string)$cl->CODIGO_INTERESSADO,
'nome_interessado' => (string)$cl->NOME_INTERESSADO,
// You will need to complete this bit
];
// Loop across each of the TELEFONE records and store them
foreach ( $cl->TELEFONES->TELEFONE as $telefone ) {
$cliente['telefones'][] = ['numero' => (string)$telefone->NUMERO,
'tipo' => (string)$telefone->TIPO
];
}
// Add the new data to the overall list
$clientes[] = $cliente;
}
}
}
}
这确实假设每个<CLIENTE>
都不很大。您可能还必须注意,数组$clientes
不会变得太大。