1

hey guys, $form holds this...

<form method="post" action="">
    <input type="hidden" name="ip" value="127.0.0.1">
    <label for="s2email">Your Email</label>
    <input type="text" name="email" id="s2email" value="email..." size="20" onfocus="if (this.value == 'email...') {this.value = '';}" onblur="if (this.value == '') {this.value = 'email...';}">
    <input type="submit" name="subscribe" value="Subscribe">
    <input type="submit" name="unsubscribe" value="Unsubscribe">
</form>

Since I have no idea what's possible with the DOMDocument class I need to ask for help. I actually have two things I need to transform on the $form above.

1.) label-s2email and its input#sd-email should be wrapped inside a <div class="name"> Is that even possible to select those two (via id or for-attribute) and wrap those two into a div?

2.) Is it possible to remove the onfocus and onblur attribute with php?

thank you for your help

matt
  • 42,713
  • 103
  • 264
  • 397
  • *(related)* [Best Methods to parse HTML](http://stackoverflow.com/questions/3577641/best-methods-to-parse-html/3577662#3577662) and [Noob Question about `DOMDocument` in PHP](http://stackoverflow.com/questions/4979836/noob-question-about-domdocument-in-php/4983721#4983721) – Gordon Mar 24 '11 at 09:27

2 Answers2

2

Since I cannot find a suitable duplicate that shows how to wrap nodes with DOM, here is the solution:

// Setup DOMDocument and XPath
$dom = new DOMDocument;
$dom->loadHTML($form);
$xpath = new DOMXPath($dom);

// Create <DIV> with class attribute name
$div = $dom->createElement('div');
$div->setAttribute('class', 'name');

// Find <input id="s2email"> and remove event attributes
$input = $xpath->query('/html/body/form/input[@id="s2email"]')->item(0);
$input->removeAttribute('onfocus');
$input->removeAttribute('onblur');

// Find <label for="s2email"> and insert new DIV before that
$label = $xpath->query('/html/body/form/label[@for="s2email"]')->item(0);
$label->parentNode->insertBefore($div, $label);

// Move <label> and <input> into the new <div>
$div->appendChild($label);
$div->appendChild($input);

// Echo the <form> outer HTML
echo $dom->saveHTML($dom->getElementsByTagName('form')->item(0));

The above code will produce (live demo):

<form method="post" action="">
    <input type="hidden" name="ip" value="127.0.0.1"><div class="name">
<label for="s2email">Your Email</label><input type="text" name="email" id="s2email" value="email..." size="20">
</div>
    <input type="submit" name="subscribe" value="Subscribe"><input type="submit" name="unsubscribe" value="Unsubscribe">
</form>

Note that in order to pass a node to saveHTML, you need PHP 5.3.6. See

for possible workarounds before that.

Community
  • 1
  • 1
Gordon
  • 312,688
  • 75
  • 539
  • 559
  • exactly the thing I want to do, perfect. I made it work with saveXML. – matt Mar 24 '11 at 13:42
  • Is there any chance I could query if the form even exists? Because once the form i submitted the page reloads and there is no form. In this case my console throws errors because all those operations on the form can not be done and nothing's found. – matt Mar 24 '11 at 13:46
  • well, the easiest would be to use `strpos` and check if $form contains "
    – Gordon Mar 24 '11 at 13:52
0

The lazy solution would be to use phpQuery or QueryPath which allow for:

print qp($html)
   ->find("*[onfocus], *[onblur]")->removeAttr("onblur")->removeAttr("onfocus")
   ->top()->find("label[for=s2email], input#s2email")->wrapAll("<div class='name'></div>")
   ->top("form")->xml();

Albeit in this case you could use DOMDocument directly. Only the wrapping part would be a bit more elaborate there. You could simpify this if you wrapped the <label> around the <input> instead of using a for= and name= relationship.

mario
  • 144,265
  • 20
  • 237
  • 291