Добавление, обновление и редактирование XML-файла с помощью PHP

У меня есть xml-файл, который я хотел бы создать в форме / таблице для добавления, редактирования и удаления записей с помощью PHP. В настоящее время я использую simpleXML для загрузки XML-файла и отображения его содержимого на разных страницах.

Есть ли способ создать таблицу, которая отображает все результаты, и позволяет мне редактировать или удалять определенную строку таблицы, которая представляет полную запись в XML-файле.

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

Мне нужно это сделать на PHP, желательно с использованием SimpleXML, хотя и открытым для предложений других способов сделать это с PHP.

ура

XSLT – ваш друг для преобразования файла базы данных XML в формат, который вы хотите отображать на веб-странице. Вы создаете XSL-шаблон, который включает в себя весь HTML, который вы хотите для каждой записи, а затем итерации через XML-файл с каждым оператором. Я дам подробный обзор и, если потребуется, может помочь с более подробной информацией.

Вот общий PHP-файл, который я использую для XSLT (обрабатываю XML-файл с XSL-файлом) через AJAX. Это настройка для работы с требуемыми (и необязательными, если требуется) входами, передаваемыми в GET-вызове из браузера. p # n и p # v (см. комментарии выше кода ниже) являются парами параметров и значений, которые должны быть переданы в документ XSL в тех случаях, когда вы хотите использовать некоторый входной параметр для воздействия на выход. В этом случае вывод возвращается в браузер. Вот PHP для запуска XML-базы данных и преобразования XSLT для создания HTML-кода для вашего веб-дисплея (таблицы или любого другого, что вы помещаете в шаблон XSL-файла):

<?php //REQUIRED INPUTS: // - xml: path to xml document // - xsl: path to xsl style sheet // - pCount: number of parameters to be passed to xslt (send zero '0' if none) //OPTIONAL INPUTS (must have as many as specified in pCount, increment '1' in //names below up a number for each iteration): // - p1n: name of first parameter // - p1v: value of first parameter //SET Paths $xmlPath = $_GET['xml']; $xslPath = $_GET['xsl']; // Load the XML source $xml = new DOMDocument; $xml->load($xmlPath); $xsl = new DOMDocument; $xsl->load($xslPath); // Configure the transformer $proc = new XSLTProcessor; $proc->importStyleSheet($xsl); // attach the xsl rules //Set Parameter(s), if present $xslParamCount = $_GET['pCount']; //Check number of xsl parameters specified in GET for ($i=1; $i<=$xslParamCount; $i++){ $xslParamName = $_GET['p'.$i.'n']; $xslParamValue = $_GET['p'.$i.'v']; $proc->setParameter( '', $xslParamName, $xslParamValue); //Set parameters for XSLTProcessor } // TRANSFORM echo $proc->transformToXML($xml); // SET Mime Type $mime = "application/xhtml+xml"; $charset = "iso-8859-1"; header("Content-Type: $mime;charset=$charset"); ?> 

Ниже приведен пример шаблона XSL-файла, который принимает документ базы данных XML и преобразует его в HTML для вставки на веб-страницу. Обратите внимание на теги HTML span. Все теги xsl обрабатывают инструкции, которые определяют, что происходит внутри и вокруг тегов HTML в шаблоне. В этом случае мы фильтруем результаты и выбираем соответствующие данные для отображения на основе входных параметров, передаваемых в XSL-файл (см. Xsl: param items at near top):

 <?xml version='1.0' encoding='UTF-8'?> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'> <xsl:param name='testId'/> <!--Input options for following param: localUse, notLocalUse, nottestId, or '' (all)--> <xsl:param name='matchType'/> <xsl:template match='/'> <xsl:choose> <xsl:when test="$matchType='localUse'"> <xsl:for-each select="//test[@id=$testId and @localUse='yes']"> <xsl:sort select="../@id"/> <div><xsl:if test='../@localPrefTestId=$testId'><xsl:attribute name='class'>preferredTest</xsl:attribute></xsl:if> <span class='productStockCode'> <xsl:if test='../@localPrefTestId=$testId'> <xsl:attribute name='title'>Preferred test for this product</xsl:attribute> </xsl:if> <xsl:if test='../@localPrefTestId!=$testId'> <xsl:attribute name='title'>Alternate (not preferred) test for this product - see note to right</xsl:attribute> </xsl:if> <xsl:value-of select='../@id'/> </span> <span class='productStockName'> <xsl:if test='../@localPrefTestId=$testId'> <xsl:attribute name='title'>Preferred test for this product</xsl:attribute> </xsl:if> <xsl:if test='../@localPrefTestId!=$testId'> <xsl:attribute name='title'>Alternate (not preferred) test for this product - see note to right</xsl:attribute> </xsl:if> <xsl:value-of select='../@name'/> </span> <span class='producttestNote'> <xsl:value-of select='child::localPrefNote'/> </span> <span class='productDeleteButton'> <input onClick='remProdLink(this)' title='Click to remove link to this product' type='image' src='button_tiny_X_grey.bmp'></input> </span> </div> </xsl:for-each> </xsl:when> <xsl:otherwise> <p>Server Error: GET must specify matchType parameter value of 'localUse', 'notLocalUse', 'nottestId', or '' (for all)</p> <p>matchType received: <xsl:value-of select='$matchType'/></p> </xsl:otherwise> </xsl:choose> </xsl:template> <!--Note the output method="html" below is required for this to insert correctly into a web page; without this it may nest improperly if any divs are empty--> <xsl:output method="html" omit-xml-declaration="yes"/> </xsl:stylesheet> в <?xml version='1.0' encoding='UTF-8'?> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'> <xsl:param name='testId'/> <!--Input options for following param: localUse, notLocalUse, nottestId, or '' (all)--> <xsl:param name='matchType'/> <xsl:template match='/'> <xsl:choose> <xsl:when test="$matchType='localUse'"> <xsl:for-each select="//test[@id=$testId and @localUse='yes']"> <xsl:sort select="../@id"/> <div><xsl:if test='../@localPrefTestId=$testId'><xsl:attribute name='class'>preferredTest</xsl:attribute></xsl:if> <span class='productStockCode'> <xsl:if test='../@localPrefTestId=$testId'> <xsl:attribute name='title'>Preferred test for this product</xsl:attribute> </xsl:if> <xsl:if test='../@localPrefTestId!=$testId'> <xsl:attribute name='title'>Alternate (not preferred) test for this product - see note to right</xsl:attribute> </xsl:if> <xsl:value-of select='../@id'/> </span> <span class='productStockName'> <xsl:if test='../@localPrefTestId=$testId'> <xsl:attribute name='title'>Preferred test for this product</xsl:attribute> </xsl:if> <xsl:if test='../@localPrefTestId!=$testId'> <xsl:attribute name='title'>Alternate (not preferred) test for this product - see note to right</xsl:attribute> </xsl:if> <xsl:value-of select='../@name'/> </span> <span class='producttestNote'> <xsl:value-of select='child::localPrefNote'/> </span> <span class='productDeleteButton'> <input onClick='remProdLink(this)' title='Click to remove link to this product' type='image' src='button_tiny_X_grey.bmp'></input> </span> </div> </xsl:for-each> </xsl:when> <xsl:otherwise> <p>Server Error: GET must specify matchType parameter value of 'localUse', 'notLocalUse', 'nottestId', or '' (for all)</p> <p>matchType received: <xsl:value-of select='$matchType'/></p> </xsl:otherwise> </xsl:choose> </xsl:template> <!--Note the output method="html" below is required for this to insert correctly into a web page; without this it may nest improperly if any divs are empty--> <xsl:output method="html" omit-xml-declaration="yes"/> </xsl:stylesheet> в <?xml version='1.0' encoding='UTF-8'?> <xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'> <xsl:param name='testId'/> <!--Input options for following param: localUse, notLocalUse, nottestId, or '' (all)--> <xsl:param name='matchType'/> <xsl:template match='/'> <xsl:choose> <xsl:when test="$matchType='localUse'"> <xsl:for-each select="//test[@id=$testId and @localUse='yes']"> <xsl:sort select="../@id"/> <div><xsl:if test='../@localPrefTestId=$testId'><xsl:attribute name='class'>preferredTest</xsl:attribute></xsl:if> <span class='productStockCode'> <xsl:if test='../@localPrefTestId=$testId'> <xsl:attribute name='title'>Preferred test for this product</xsl:attribute> </xsl:if> <xsl:if test='../@localPrefTestId!=$testId'> <xsl:attribute name='title'>Alternate (not preferred) test for this product - see note to right</xsl:attribute> </xsl:if> <xsl:value-of select='../@id'/> </span> <span class='productStockName'> <xsl:if test='../@localPrefTestId=$testId'> <xsl:attribute name='title'>Preferred test for this product</xsl:attribute> </xsl:if> <xsl:if test='../@localPrefTestId!=$testId'> <xsl:attribute name='title'>Alternate (not preferred) test for this product - see note to right</xsl:attribute> </xsl:if> <xsl:value-of select='../@name'/> </span> <span class='producttestNote'> <xsl:value-of select='child::localPrefNote'/> </span> <span class='productDeleteButton'> <input onClick='remProdLink(this)' title='Click to remove link to this product' type='image' src='button_tiny_X_grey.bmp'></input> </span> </div> </xsl:for-each> </xsl:when> <xsl:otherwise> <p>Server Error: GET must specify matchType parameter value of 'localUse', 'notLocalUse', 'nottestId', or '' (for all)</p> <p>matchType received: <xsl:value-of select='$matchType'/></p> </xsl:otherwise> </xsl:choose> </xsl:template> <!--Note the output method="html" below is required for this to insert correctly into a web page; without this it may nest improperly if any divs are empty--> <xsl:output method="html" omit-xml-declaration="yes"/> </xsl:stylesheet> 

Обратите внимание, что все тесты xsl представляют собой выражения XPath.

Чтобы удалить строку, вы можете иметь кнопку в этой строке, которая вызывает функцию JavaScript с аргументом «this» (см. OnClick = 'remProdLink (this)' в коде выше) для ссылки на строку, а затем захватить уникальный идентификатор строка в JavaScript примерно так:

 function remProdLink(obj){ //get unique id via Dom from passed in object reference //edit everything after "obj" below to get to the unique id in the record var testCode = obj.parentNode.parentNode.firstChild.nextSibling.innerHTML; //code to send AJAX POST to server with required information goes here } 

На стороне сервера ваш PHP получает AJAX POST с уникальным идентификатором, загружает файл базы данных XML в simpleXml, находит узел через XPath и удаляет его, что-то вроде этого:

 <?php //Move url encoded post data into variables $testCode = $_POST['testCode']; //$testCode should be a unique id for the record //load xml file to edit $xml = simplexml_load_file('yourDatabase.xml'); //find target node for removal with XPath $targets = $xml->xpath("//testCode[@id=$testCode]"); //import simpleXml reference into Dom to do removal $dom2 = dom_import_simplexml($targets[0]); $dom2->parentNode->removeChild($dom2); //format xml to save indented tree (rather than one line) and save $dom = new DOMDocument('1.0'); $dom->preserveWhiteSpace = false; $dom->formatOutput = true; $dom->loadXML($xml->asXML()); $dom->save('yourDatabase.xml'); ?> 

Что касается редактирования элемента, вы можете использовать другую функцию JavaScript, аналогичную той, которая была удалена, как указано выше, создать форму под этим элементом на веб-странице с кнопкой сохранения изменений, и когда эта кнопка будет нажата, вызовите другую функцию JavaScript для AJAX POST на сервер, снова аналогично удалению. Только на этот раз ваш POST должен будет включить всю информацию, которая могла быть отредактирована в записи вместе с уникальным идентификатором записи. Файл PHP найдет соответствующую запись (то же, что и для удаления), а затем вы можете отредактировать части этой записи в PHP или просто удалить ее и создать и добавить новую версию записи.

Я не уверен, сколько деталей вам нужно. Надеюсь, это даст вам хорошее начало. Прокомментируйте мой ответ, если вам нужна подробная информация о любой его части. Удачи!

Я бы предположил, что вы используете DomDocument и DomXPath, а не SimpleXml. Однако, как правило, XML не является оптимальным средством для хранения данных. Вероятно, вы должны использовать базу данных для всего, что вы делаете. Если вам нужно легко обмениваться данными, вы можете использовать SQLite вместо более распространенного MySql.

Вы можете использовать собственную базу данных XML для облегчения создания, добавления, обновления и извлечения XML-документов и узлов. Я использовал BerkeleyDBXML (теперь часть Oracle) в прошлом с успехом. Существует также библиотека PHP.