Редактирование XML

Данные, хранящиеся в XML файле, можно редактировать прямо в клиентском браузере.

Открытие, редактирование и сохранение XML

В этой главе будет показано как открывать, редактировать и сохранять XML файл, хранящийся на сервере.

Для этого мы будем использовать XSL, чтобы преобразовать XML документ в HTML форму. Значения XML элементов будут записываться в поля ввода в HTML форме. HTML форму можно будет редактировать. После редактирования данные можно будет отправить на сервер, и XML файл будет обновлен (мы покажем соответствующий код на PHP и ASP).

XML и XSL файлы

Для примера возьмем следующий XML документ ("tool.xml"):


<?xml version="1.0" encoding="UTF-8"?>
<tool>
   <field id="prodName">
     <value>HAMMER HG2606</value>
   </field>
   <field id="prodNo">
     <value>32456240</value>
   </field>
   <field id="price">
     <value>$30.00</value>
   </field>
</tool>

И соответствующую таблицу стилей XSL ("tool.xsl"):


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
   <html>
   <body>
   <form method="post" action="//msiter.ru/edittool.php">
   <h2>Tool Information (edit):</h2>
   <table border="0">
     <xsl:for-each select="tool/field">
     <tr>
       <td><xsl:value-of select="@id"/></td>
       <td>
       <input type="text">
       <xsl:attribute name="id">
         <xsl:value-of select="@id" />
       </xsl:attribute>
       <xsl:attribute name="name">
         <xsl:value-of select="@id" />
       </xsl:attribute>
       <xsl:attribute name="value">
         <xsl:value-of select="value" />
       </xsl:attribute>
       </input>
       </td>
     </tr>
     </xsl:for-each>
   </table>
   <br />
   <input type="submit" id="btn_sub" name="btn_sub" value="Submit" />
   <input type="reset" id="btn_res" name="btn_res" value="Reset" />
   </form>
   </body>
   </html>
</xsl:template>

</xsl:stylesheet>

Код в приведенном выше XSL файле в цикле проходит по элементам XML файла и создает поле ввода для каждого XML элемента-"поля".

Значение атрибута "id" XML элемента-"поля" добавляется одновременно в атрибуты "id" и "name" каждого HTML поля ввода. Значение каждого XML элемента "value" добавляется в атрибут "value" каждого HTML поля ввода. В результате мы получаем редактируемую HTML форму, содержащую значения из XML файла.

Наконец, мы определяем вторую таблицу стилей XSL: "tool_updated.xsl". Этот XSL файл будет использоваться для отображения обновленных XML данных. Данная таблица стилей формирует не HTML форму, а статическую HTML таблицу:


<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
   <html>
   <body>
   <h2>Updated Tool Information:</h2>
   <table border="1">
     <xsl:for-each select="tool/field">
     <tr>
       <td><xsl:value-of select="@id" /></td>
       <td><xsl:value-of select="value" /></td>
     </tr>
     </xsl:for-each>
   </table>
   </body>
   </html>
</xsl:template>

</xsl:stylesheet>

PHP файл

В файле "tool.xsl" указываем в атрибуте action формы файл "edittool.php".

Файл "edittool.php" содержит две функции: функция loadFile() загружает и преобразовывает XML файл для дальнейшего отображения, а функция updateFile() применяет сделанные изменения в XML файле:


<?php
function loadFile($xml, $xsl)
{
   $xmlDoc = new DOMDocument();
   $xmlDoc->load($xml);

   $xslDoc = new DOMDocument();
   $xslDoc->load($xsl);

   $proc = new XSLTProcessor();
   $proc->importStyleSheet($xslDoc);
   echo $proc->transformToXML($xmlDoc);
}

function updateFile($xml)
{
   $xmlLoad = simplexml_load_file($xml);
   $postKeys = array_keys($_POST);

   foreach($xmlLoad->children() as $x)
   { 
      foreach($_POST as $key=>$value)
      { 
         if($key == $x->attributes())
         {
            $x->value = $value;
         }
      }
   }

   $xmlLoad->asXML($xml);
   loadFile($xml,"tool_updated.xsl");
}

if($_POST["btn_sub"] == "")
{
   loadFile("tool.xml", "tool.xsl");
 }
 else
 {
    updateFile("tool.xml");
 }
?>

Примечание: Все преобразования и изменения XML файла делаются на сервере. Это кросс-браузерное решение. Пользователь получит только HTML страницу, что будет работать в любом браузере.

ASP файл

В файле "tool.xsl" указываем в атрибуте action формы файл "edittool.asp".

Файл "edittool.asp" содержит две функции: функция loadFile() загружает и преобразовывает XML файл для дальнейшего отображения, а функция updateFile() применяет сделанные изменения в XML файле:


<%
function loadFile(xmlfile,xslfile)
   Dim xmlDoc,xslDoc
   'Загружаем XML и XSL файлы
   set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")
   xmlDoc.async = false
   xmlDoc.load(xmlfile)
   set xslDoc = Server.CreateObject("Microsoft.XMLDOM")
   xslDoc.async = false
   xslDoc.load(xslfile)
   'Преобразовываем файл
   Response.Write(xmlDoc.transformNode(xslDoc))
end function

function updateFile(xmlfile)
   Dim xmlDoc,rootEl,f
   Dim i
   'Загружаем XML файл
   set xmlDoc = Server.CreateObject("Microsoft.XMLDOM")
   xmlDoc.async = false
   xmlDoc.load(xmlfile)

   'Устанавливаем переменную rootEl равную корневому элементу
   Set rootEl = xmlDoc.documentElement

   'Цикл по набору формы
   for i = 1 To Request.Form.Count
      'Убираем элементы кнопок в форме
      if instr(1,Request.Form.Key(i),"btn_")=0 then
         'Метод selectSingleNode запрашивает XML файл на наличие одиночного узла,
         'соответствующего запросу. Данный запрос ищет элемент value, который
         'является потомком элемента field, у которого атрибут id соответствует
         'текущему ключу в Form Collection. Когда соответствие будет найдено,
         'установить свойство text равным значению текущего поля в Form Collection.
         set f = rootEl.selectSingleNode("field[@id='" & _
            Request.Form.Key(i) & "']/value")
         f.Text = Request.Form(i)
      end if
   next

   'Сохранить модифицированный XML файл
   xmlDoc.save xmlfile

   'Освобождаем все ссылки на объекты
   set xmlDoc=nothing
   set rootEl=nothing
   set f=nothing

   'Загружаем модифицированный XML файл с таблицей стилей,
   'которая позволит пользователю увидеть отредактированную информацию
   loadFile xmlfile,server.MapPath("tool_updated.xsl")
end function

'Если форма была отправлена, обновить XML файл и отобразить результат
'Если нет, преобразовать XML файл для редактирования
if Request.Form("btn_sub")="" then
   loadFile server.MapPath("tool.xml"),server.MapPath("tool.xsl")
else
   updateFile server.MapPath("tool.xml")
end if
%>