【问题标题】:Add, update and edit an XML file with PHP使用 PHP 添加、更新和编辑 XML 文件
【发布时间】:2008-12-18 11:59:25
【问题描述】:

我有一个 xml 文件,我想围绕它创建一个表单/表格,以使用 PHP 添加、编辑和删除记录。目前我使用simpleXML来加载XML文件,并将其内容显示在各个页面上。

有什么方法可以创建一个显示所有结果的表,并允许我编辑或删除表中代表 XML 文件中的完整记录的特定行。

单击编辑时,我希望记录中的详细信息以用户可以更改然后保存的形式出现,从而更新 XML 文件和相应的网页。

我需要在 PHP 中完成此操作,最好使用 SimpleXML,尽管对使用 PHP 执行此操作的其他方法的建议持开放态度。

干杯

【问题讨论】:

    标签: php xml simplexml


    【解决方案1】:

    XSLT 是您将 XML 数据库文件转换为您希望在网页上显示的格式的朋友。您创建一个 XSL 模板,其中包含每条记录所需的所有 HTML,然后使用 for-each 语句遍历 XML 文件。我会给出一个粗略的概述,如果需要,我会提供更多详细信息。

    这是我用来通过 AJAX 执行 XSLT(使用 XSL 文件处理 XML 文件)的通用 PHP 文件。这个设置用于处理从浏览器的 GET 调用中传递的必需(和可选,如果需要)输入。 p#n 和 p#v(参见下面代码顶部的 cmets)是要传递到 XSL 文档中的参数和值对,以防您希望使用某些输入参数来影响输出。在这种情况下,输出会回显到浏览器。下面是运行 XML 数据库的 PHP 和 XSLT 转换来为您的 Web 显示(表格,或您在 XSL 文件模板中放置的任何内容)创建 HTML:

    <?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 跨度标记。所有 xsl 标记都是处理指令,用于确定模板中 HTML 标记及其周围的内容。在这种情况下,我们根据传入 XSL 文件的输入参数过滤结果并选择要显示的适当数据(请参阅顶部附近的 xsl:param 项):

    <?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 表达式。

    要删除一行,您可以在该行上设置一个按钮,该按钮使用“this”参数调用 JavaScript 函数(参见上面代码中的 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 需要包含记录中可能已编辑的所有信息以及记录的唯一 ID。 PHP 文件将找到适当的记录(与删除相同),然后您可以在 PHP 中编辑该记录的部分内容,或者直接删除它并创建并附加新版本的记录。

    我不确定您需要多少详细信息。希望这能给你一个好的开始。如果您需要有关任何部分的更多详细信息,请评论我的回答。祝你好运!

    【讨论】:

    • 你的答案包括关于 $dom 的最后一段代码中的一行: //import simpleXml reference into Dom to do remove $dom2 = dom_import_simplexml($targets[0 ]); $dom2->parentNode->removeChild($dom);但我没有注意到 $dom 在那段代码之前初始化。你能进一步解释那部分吗?感谢您的输入和详细的示例。
    • @predikt:感谢您发现这个错字。它应该是 removeChild($dom2)。答案已更新。
    【解决方案2】:

    我建议您使用 DomDocument 和 DomXPath,而不是 SimpleXml。然而,一般来说,XML 并不是存储数据的最佳媒介——无论您正在做什么,您都应该使用数据库。如果您需要轻松交换数据,您也许可以使用 SQLite,而不是更常见的 MySql。

    【讨论】:

      【解决方案3】:

      您可以使用原生 XML 数据库来促进创建、添加、更新和检索 xml 文档和节点。我过去成功地使用过BerkeleyDBXML(现在是Oracle 的一部分)。还有一个 PHP 库可用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-31
        • 2011-09-23
        • 1970-01-01
        • 1970-01-01
        • 2010-09-15
        • 1970-01-01
        相关资源
        最近更新 更多