Skip to content
Advertisement

Edit XML file on web page and save back to XML file using PHP

I have an XML file with a list of events and need to edit them via a web page, and when the edited data is submitted then it needs to be saved back to the XML file.

I have used an XSL file to display the XML on the web page. For each node it displays an empty input box with the node value to the right. How can I get the node value to appear inside the input text box? And how can I get the node name to appear on the left of the input text box?

The next problem is that once this has been edited then how can I get it stored back in the XML file with exactly the same structure?

One more thing, how can I add or remove an event? Thanks.

Here’s the XML file:

<?xml version="1.0" encoding="UTF-8"?>
<events>
    <event>
        <id>ev01</id>
        <date>31/12/2020</date>
        <start-time>09:00</start-time>
        <end-time>12:00</end-time>
        <title>Event #1</title>
        <cost>20</cost>
        <venue>London</venue>
        <available-places>10</available-places>
        <updates><![CDATA[We'll post updates here]]></updates>
    </event>
    <event>
        <id>ev02</id>
        <date>31/12/2020</date>
        <start-time>13:00</start-time>
        <end-time>17:00</end-time>
        <title>Event #2</title>
        <cost>20</cost>
        <venue>London</venue>
        <available-places>Sold out</available-places>
        <updates><![CDATA[We'll post updates here]]></updates>
    </event>
</events>

And here’s the XSL file:

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

<xsl:template match="/events">
  <div id="edit_xml">
  <h2>My events</h2>
  <form method="post" action="#edit_xml">
    <xsl:for-each select="event/*">
      <p>
      <input type="text" id="" name="" value="">
      <xsl:value-of select="." />
      </input>
      </p>
    </xsl:for-each>
    <p><input type="submit" name="submit_data" value="Submit"/></p>
  </form>
  </div>
</xsl:template>

</xsl:stylesheet>

Advertisement

Answer

To answer your XSLT questions to render HTML form:

How can I get the node value to appear inside the input text box? And how can I get the node name to appear on the left of the input text box? … One more thing, how can I add or remove an event?

Consider adjusting XSLT to use name() and assign value with expression: {text()}. And even wrap node name inside <label> tag with styling for alignment. Even more, add a unique <input> id (for CSS/Javascript to identify) and name (for PHP to identify) using XSLT functions: name() and position(). For better management of each event, separate script into event and events templates

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>
    
    <xsl:template match="/events">
        <div id="edit_xml">
          <h2>My events</h2>
             <form method="post" action="#edit_xml">
                 <xsl:apply-templates select="event"/>
                 <p><input type="submit" name="submit_data" value="Submit"/></p>
             </form>
        </div>
    </xsl:template>
    
    <xsl:template match="event">
        <xsl:for-each select="*">
          <p>
              <label style="display: inline-block;width: 140px;">
                  <xsl:value-of select="name()"/>
              </label>
              <input type="text" id="{concat(name(), position())}" 
                     name="{concat(name(), position())}" 
                     value="{text()}"/>
          </p>
        </xsl:for-each>
    </xsl:template>

</xsl:stylesheet>

Online Demo

HTML Output

To remove an element, run bracketed [] condition in <xsl:apply-templates> in top layer events template:

<!-- SELECT ONLY FIRST event TO BE APPLIED -->
<xsl:apply-templates select="event[1]"/>

<!-- SELECT ONLY SECOND event TO BE APPLIED -->
<xsl:apply-templates select="event[2]"/>

<!-- SELECT ALL NODES AFTER FIRST event -->
<xsl:apply-templates select="event[position() &gt; 1]"/>

<!-- SELECT ALL NODES BUT EXCLUDE SECOND NODE -->
<xsl:apply-templates select="event[position() != 2]"/>

<!-- SELECT ONLY LAST event TO BE APPLIED -->
<xsl:apply-templates select="event[last()]"/>

For this non-XSLT question:

The next problem is that once this has been edited then how can I get it stored back in the XML file with exactly the same structure?

You need to handle the form submission with application layer like in PHP to receive input values and bind into XML document. In fact, you can set up another XSLT solution with exact original layout to receive parameters from PHP!

User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement