Funções
Primeiro, cria-se um objeto Document DOM que pode ser usado para manipular os dados. Abra o arquivo scripts.txt e inclua o seguinte código:
...
define(UPLOADEDFILES, "/var/www/hidden/");
function save_document_info($fileInfo){
$doc = new DOMDocument('1.0');
}
?>
|
O processo real de criação de um objeto Document , neste caso chamado de $doc, é direto.
A classe DOMDocument faz parte do núcleo do PHP V5. Esse objeto é usado para executar a maior parte de suas ações nos dados.
Agora, que há um Document funcional, é possível usá-lo para criar o elemento principal ou raiz do documento:
...
function save_document_info($fileInfo){
$doc = new DOMDocument('1.0');
$root = $doc->createElement('workflow');
$doc->appendChild($root);
}
...
|
Aqui, indica-se ao objeto $doc que deve criar um novo elemento e retorná-lo à variável $root
. Indica-se então a Document que deve incluir esse elemento como seu filho.
Mas o que acontece se esse documento for salvo como um arquivo?
Salvar o Documento em um Arquivo
Uma vantagem de usar PHP para processar seu XML é que PHP fornece uma maneira fácil de salvar o conteúdo de um
Document em um arquivo. (Acredite se quiser, mas nem sempre é tão fácil assim.) Para ver o que está realmente sendo gerado, inclua o código a seguir em
save_document_info():
...
function save_document_info($fileInfo){
$doc = new DOMDocument('1.0');
$root = $doc->createElement('workflow');
$doc->appendChild($root);
$doc->save(UPLOADEDFILES."docinfo.xml");
}
...
|
A constante UPLOADEDFILES foi definida anteriormente, portanto, pode simplesmente seguir em frente e fazer referência a ela agora, colocando o novo arquivo no mesmo diretório.
Se agora fizer upload de um arquivo através do navegador, o arquivo docinfo.xml deve ter a seguinte aparência:n
<?xml version="1.0"?> <workflow/> |
Não se preocupe com a primeira linha, é a declaração XML e é padrão, mas é opcional (na maioria dos casos).
Observe que seu elemento foi salvo, mas como não incluiu ainda no mesmo nenhum filho nem conteúdo realmente, é gravado como um elemento vazio.
Agora, vamos incluir um elemento mais complicado.
Inicie a inclusão de informações reais no arquivo. Um arquivo já foi criado para testar a etapa anterior, mas até salvar completamente as informações do primeiro arquivo, pode-se supor que ainda esteja criando o arquivo docinfo.xml.
Inicie criando o elemento statistics :
...
function save_document_info($fileInfo){
$doc = new DOMDocument('1.0');
$root = $doc->createElement('workflow');
$doc->appendChild($root);
$statistics = $doc->createElement("statistics");
$statistics->setAttribute("total", "1");
$statistics->setAttribute("approved", "0");
$root->appendChild($statistics);
$doc->save(UPLOADEDFILES."docinfo.xml");
}
...
|
Observe que Document será usado para criar o novo elemento, desta vez chamado de
statistics. O Document age como uma "fábrica" para a maioria de seus objetos.
Quando tiver o objeto Element , $statistics, é possível usar suas funções integradas para configurar dois atributos:
total e approved. Após fazer isso, deve incluir esse elemento como um filho de
$root, em vez de um filho de $doc. Se salvar o arquivo, poderá ver a diferença:
<?xml version="1.0"> <workflow><statistics total="1" approved="0"/></workflow> |
Perceberá duas coisas aqui. Primeiro, observe que o elemento statistics é filho do elemento
workflow . Observe também que não há nenhum espaço em branco irrelevante aqui. O elemento statistics
é o primeiro filho do workflow.
Agora, vamos dar uma olhada em incluir informações reais.
Criar o Elemento de Informações do Arquivo
Agora, é possível seguinte em frente e criar as informações reais do documento. O processo usa as técnicas que você acabou de aprender.
...
function save_document_info($fileInfo){
$doc = new DOMDocument('1.0');
$root = $doc->createElement('workflow');
$doc->appendChild($root);
$statistics = $doc->createElement("statistics");
$statistics->setAttribute("total", "1");
$statistics->setAttribute("approved", "0");
$root->appendChild($statistics);
$filename = $fileInfo['name'];
$filetype = $fileInfo['type'];
$filesize = $fileInfo['size'];
$fileInfo = $doc->createElement("fileInfo");
$fileInfo->setAttribute("status", "pending");
$fileInfo->setAttribute("submittedBy", $_SESSION["username"]);
$approvedBy = $doc->createElement("approvedBy");
$fileName = $doc->createElement("fileName");
$fileNameText = $doc->createTextNode($filename);
$fileName->appendChild($fileNameText);
$location = $doc->createElement("location");
$locationText = $doc->createTextNode(UPLOADEDFILES);
$location->appendChild($locationText);
$type = $doc->createElement("fileType");
$typeText = $doc->createTextNode($filetype);
$type->appendChild($typeText);
$size = $doc->createElement("size");
$sizeText = $doc->createTextNode($filesize);
$size->appendChild($sizeText);
$fileInfo->appendChild($approvedBy);
$fileInfo->appendChild($fileName);
$fileInfo->appendChild($location);
$fileInfo->appendChild($type);
$fileInfo->appendChild($size);
$root->appendChild($fileInfo);
$doc->save(UPLOADEDFILES."docinfo.xml");
}
...
|
Apesar de haver muito código aqui, muito pouco é novo. Primeiro, extrai-se as informações reais sobre o arquivo das informações passadas para a função.
Cria-se então o elemento fileInfo que conterá todas as informações que estão sendo incluídas.
Configura-se os atributos status e submittedBy nesse elemento e verifica-se então a criação de seus elementos.
O elemento approvedBy é fácil. Ainda não foi aprovado, portanto, isso permanecerá vazio. O elemento
fileName , por outro lado, é um pouco mais difícil, pois é necessário incluir um filho de texto no mesmo.
Felizmente, isso também é bem direto. O elemento é criado, então,
Document é usado para criar o novo nó de texto que tem como seu conteúdo o nome do arquivo. Pode-se então incluir esse nó de texto como filho do elemento
fileName .
É possível progredir dessa forma, criando todos os elementos que, eventualmente, serão filhos de fileInfo.
Após ter concluído, todos são anexados como filhos do elemento fileInfo . Por fim, o próprio elemento
fileInfo é incluído no elemento-raiz, workflow.
Os resultados, com espaçamento incluído por questão de clareza, têm aparência semelhante ao seguinte:
<?xml version="1.0"?>
<workflow>
<statistics total="1" approved="0"/>
<fileInfo status="pending" submittedBy="roadnick">
<approvedBy/>
<fileName>signed.pem</fileName>
<location>/var/www/hidden/</location>
<fileType>application/octet-stream</fileType>
<size>2754</size>
</fileInfo>
</workflow>
|
É claro que não é possível continuar sobrescrevendo o arquivo de informações toda vez que alguém faz upload de um documento, portanto, em seguida, verá como é trabalhar com uma estrutura existente.
Inserindo um Documento Existente
Agora que já sabe como incluir informações no arquivo, é necessário verificar como trabalhar com o arquivo em uploads subsequentes. Primeiro, é necessário ver se o arquivo já existe, então agir conforme necessário:
...
function save_document_info($fileInfo){
$xmlfile = UPLOADEDFILES."docinfo.xml";
if(is_file($xmlfile)){
$doc = DOMDocument::load($xmlfile);
$workflowElements = $doc->getElementsByTagName("workflow");
$root = $workflowElements->item(0);
} else{
$doc = new DOMDocument('1.0');
$root = $doc->createElement('workflow');
$doc->appendChild($root);
$statistics = $doc->createElement("statistics");
$statistics->setAttribute("total", "1");
$statistics->setAttribute("approved", "0");
$root->appendChild($statistics);
}
$filename = $fileInfo['name'];
$filetype = $fileInfo['type'];
$filesize = $fileInfo['size'];
$fileInfo = $doc->createElement("fileInfo");
...
$fileInfo->appendChild($size);
$root->appendChild($fileInfo);
$doc->save($xmlfile);
}
|
Iniciando na parte superior, cria-se uma varável para representar o local do arquivo, já que agora será feita referência a ele em mais de um local.
Em seguida, verifica-se se esse arquivo já existe. Se existir, a função
load() é chamada, em vez de cria-se um novo objeto.
Essa função estática -- sobre a qual falaremos mais na Parte 3 desta série; por ora, entenda que são funções que podem ser chamadas a partir da classe, em vez de a partir de um objeto -- retorna um objeto
Document
que já está preenchido com todos os elementos, texto, etc., representados no arquivo.
Quando tiver o objeto Document , o elemento workflow será necessário, pois, no final, será necessário incluir o novo elemento
fileInfo no mesmo. Obtém-se o elemento workflow recuperando primeiro uma lista de todos os elementos do documento chamado
workflow e então selecionando o primeiro da lista.
A partir de então, é possível simplesmente incluir o novo elemento fileInfo e ele aparecerá após o original.
Novamente, com espaço incluído por questão de clareza:
<?xml version="1.0"?>
<workflow>
<statistics total="1" approved="0"/>
<fileInfo status="pending" submittedBy="roadnick">
...
</fileInfo>
<fileInfo status="pending" submittedBy="roadnick">
<approvedBy/>
<fileName>timeone.jpg</fileName>
<location>/var/www/hidden/</location>
<fileType>image/jpeg</fileType>
<size>2020</size>
</fileInfo>
</workflow>
|
E statistics? Obviamente, não estão mais corretos. Isso precisará ser resolvido.
Além de incluir informações no documento, é possível alterar informações que já estão lá. Por exemplo, é possível atualizar o atributo
total no elemento statistics :
...
if(is_file($xmlfile)){
$doc = DOMDocument::load($xmlfile);
$workflowElements = $doc->getElementsByTagName("workflow");
$root = $workflowElements->item(0);
$statistics = $root->getElementsByTagName("statistics")->item(0);
$total = $statistics->getAttribute("total");
$statistics->setAttribute("total", $total + 1);
} else{
...
|
Primeiramente, obtém-se uma referência ao elemento statistics existente da mesma forma que obteve-se do elemento
workflow existente, apenas combina-se ambas as etapas em uma. Quando tiver uma referência para o elemento, é possível obter o valor atual do atributo
total usando a função getAttribute()
. Pode-se usar então esse valor para fornecer um valor atualizado para o atributo total usando
setAttribute().
Os resultados são os que podem ser esperados, desta vez, sem espaços incluídos:
<?xml version="1.0"?> <workflow><statistics total="2" approved="0"/><fileInfo status="pending" submittedBy="roadnick">... |
Agora que já sabe como usar o DOM para criar o arquivo, vamos dar uma olhada em como lê-lo novamente usando outra API XL, SAX.
