I've added a comment to the documentation for form_set_value with my findings from the last few hours. I though you might want the code example. I'll copy it at the end of this post so you can review more quickly, and merge in an example if you like. I think you may want to pay special attention to the forum post I linked. There's a lot of different keywords from search engines hitting it.
I hope I help someone with this.

Cheers, Lance!

______________________________
Having fought with this for a couple hours now, I thought I'd leave notes of what I found here.
Before I begin:
http://drupal.org/node/160160 is unclear, but is the top result after this page on search engines due to length. This page may need to be updated if the proper documentation can not be understood from this page.

When using drupal 6, this is the process you must use:

Optional

<?php
function hook_form(){
//... Previous Code
// You *can* (and should) declare a placeholder for the value to be inserted into later.
$form['placeholder'] = array(
'#type' => 'value'
,'#value' = > NULL // Placeholder value. Meaningless
);
//... Other Code
}
?>

Required

Because the form_set_value function requires more arguments than standard hook_validate functions provide, you must use hook_form_alter to do custom validation for your form:

<?php
function hook_form_alter(&$form, $form_state, $form_id){
if (
$form_id == '{node_type}_node_form') {
 
$form['#validate'][] = 'hook_validate_custom';
}
?>

With the form set to validate through your new function, create it. Note that $form_state must be a reference.

<?php
hook_validate_custom
($form, &$form_state){
// ... Validation Code
form_set_value( array('#parents' => array('array_key_parent', 'array_key_to_replace')) , $value, $form_state);
// ... Other Code
}
?>

Sorry for the inline array.
Here's a breakdown of the three parameters you must pass in:
  1. An array with one item: '#parents'. '#parents' is another array. '#parents' should be the arrays keys needed to reach the form value you want to replace. For instance:
    <?php
    $first_parameter
    = array(
    '#parents' => array(
     
    'first_key_in_path'
     
    ,'second_key_in_path'
     
    ,'key_to_replace' // Always the last one. *Will* create if it doesn't exist.
    )
    );
    ?>
  2. The value you want inserted.
  3. $form_state
Files: 
CommentFileSizeAuthor
#31 documentation_form_set_value-570314-31.patch1.2 KBMac_Weber
PASSED: [[SimpleTest]]: [MySQL] 33,451 pass(es).
[ View ]
#30 documentation_form_set_value-570314-30.patch1.12 KBMac_Weber
PASSED: [[SimpleTest]]: [MySQL] 33,445 pass(es).
[ View ]
#27 documentation_form_set_value-570314-27.patch1.24 KBMac_Weber
PASSED: [[SimpleTest]]: [MySQL] 33,445 pass(es).
[ View ]
#16 570314new.patch1.02 KBjhodgdon
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 570314new.patch. See the log in the details link for more information.
[ View ]
#9 570314update.patch1017 bytesjhodgdon
PASSED: [[SimpleTest]]: [MySQL] 17,540 pass(es).
[ View ]
#2 570314.patch2.79 KBjhodgdon
Passed on all environments.
[ View ]

Comments

I took a look at this example... So I'm sorry, but I am unsure what you are trying to accomplish here, and which documentation you would like to see changed. Can you please explain?

a) What is your hook_form() implementation really doing? I don't see that being used anywhere else in your example.

b) The documenation on http://api.drupal.org/api/function/form_set_value already says:

Since $form_state['values'] can either be a flat array of values, or a tree of nested values, some care must be taken when using this function. Specifically, $form_item['#parents'] is an array that describes the branch of the tree whose value should be updated. For example, if we wanted to update $form_state['values']['one']['two'] to 'new value', we'd pass in $form_item['#parents'] = array('one', 'two') and $value = 'new value'.

It looks to me like it explains how to set $parents... what more is your example doing that needs to be explained better? Is it just that you think it should explain how to add a validation function using hook_form_alter? If so, that's probably a good idea.

Title:Documentation problem with form_set_valueform_set_value() documentation needs more detail
Version:6.x-dev» 7.x-dev
Status:Active» Needs review
StatusFileSize
new2.79 KB
Passed on all environments.
[ View ]

Assuming that what is wanted is more detail added on how to define a validation function, here's a patch, which I think also explains better how/where to call form_set_value.

Patch is against Drupal 7. If accepted, should be back ported to Drupal 6.

I also recommend that the comment http://api.drupal.org/api/function/form_set_value#comment-49 be removed if this patch is committed (and maybe even if this patch isn't committed). (I don't have/want comment delete priveleges on api.drupal.org.)

jhodgdon requested that failed test be re-tested.

Status:Needs review» Fixed

Committed to CVS HEAD. Thanks.

Status:Fixed» Needs work

We should additionally clarify that form_set_value() _only_ sets the value in $form_state['values']. Not in $element['#value'].

And we should clarify *why* it is that way.

Ummm... I think the doc does imply that the value is stored in $form_state. I'm not sure it needs more clarification... sun, maybe you can propose a patch that would add the clarification you think is needed?

And as a note, we do need to port the above change (and any other changes in subsequent patches) to Drupal 6 once this is fixed in D7.

while you are at it
why keeping $element being recursively passed in _form_set_value while it isn't used at all?

its current signature

<?php
function _form_set_value(&$form_values, $element, $parents, $value) {
?>

should be

<?php
function _form_set_value(&$form_values, $parents, $value) {
?>

since $element is not needed in the helper function neither used, just passed through

BTW, with "just passed through" I meant "to it self" (which is silly)

Status:Needs work» Needs review
StatusFileSize
new1017 bytes
PASSED: [[SimpleTest]]: [MySQL] 17,540 pass(es).
[ View ]

Here's an update patch that addresses #5 (clarifies further that values are only set in $form_state).

As far as #7 and #8 -- I think it is way too late in the development cycle to change how form_set_value() is called for Drupal 7. If you feel strongly about it, please file a new issue for Drupal 8 with your suggestion. It might be a pain to patch, though, because you'd also have to find all the spots in the core Drupal code that call this function and update them.

@#9 is a private function for internal use of form_set_value (to do the recursive dirty work)

<?php
/**
* Helper function for form_set_value().
*
?>

I do not understand #10. ???

Ah. I see what you are saying in #10: that only the internal recursive function _form_set_value() needs to be changed.

So yes, that is an OK idea. But please file it as a separate issue, and if possible, create a patch.

Looks good, just one minor thing:

+++ includes/form.inc 5 Feb 2010 15:28:23 -0000
@@ -1738,11 +1738,13 @@
  * validation function, so that the changed value persists in $form_state
+ * through to the submission handlers. It does not change the values that may

The value is also persisted in $form_state through to any additional validation handlers if there are any left. Maybe this should just read "handlers" instead of "submission handlers"?

144 critical left. Go review some!

Status:Needs review» Needs work

Good point.

Status:Needs work» Needs review

Actually, it says "through to the submission handlers", indicating it should persist and keep persisting up through the submission handlers, so I think it's OK?

StatusFileSize
new1.02 KB
FAILED: [[SimpleTest]]: [MySQL] Unable to apply patch 570314new.patch. See the log in the details link for more information.
[ View ]

On second thought, I think your idea is good to include validation handlers in there. Here's some revised language.

Status:Needs review» Needs work

The last submitted patch, 570314new.patch, failed testing.

Status:Needs work» Needs review

#16: 570314new.patch queued for re-testing.

#16: 570314new.patch queued for re-testing.

#16: 570314new.patch queued for re-testing.

#16: 570314new.patch queued for re-testing.

#16: 570314new.patch queued for re-testing.

Version:7.x-dev» 8.x-dev
Issue tags:+needs backport to D7

updating, will click retest in a sec...

Issue tags:-needs backport to D7

#16: 570314new.patch queued for re-testing.

Status:Needs review» Needs work
Issue tags:+needs backport to D7

The last submitted patch, 570314new.patch, failed testing.

Issue tags:+Novice

Needs a re-roll. Probably a good novice project?

Status:Needs work» Needs review
StatusFileSize
new1.24 KB
PASSED: [[SimpleTest]]: [MySQL] 33,445 pass(es).
[ View ]

re-rolled patch #16

Thanks for the patch re-roll! I wrote the original so I cannot mark it "reviewed". Anyone else?

Status:Needs review» Needs work

+++ b/includes/form.inc
@@ -2403,11 +2403,13 @@ function form_type_token_value($element, $input = FALSE) {
+ * Changes submitted form values (in $form_state) during form validation.

Let's remove the parenthesis.

Also, I think the limitation to "during form validation" is not necessarily needed; technically it's also valid to use in submission handlers. However, we can also leave it as is...

+++ b/includes/form.inc
@@ -2403,11 +2403,13 @@ function form_type_token_value($element, $input = FALSE) {
+ * through the remaining validation and submission handlers. It does not change
+ * the values that may be present in the $element array, but only in
+ * $form_state, which is where the submitted values are always stored.

It does not change the value in $element['#value'], only in $form_state['values'], which is where submitted values are always stored.

-16 days to next Drupal core point release.

Status:Needs work» Needs review
StatusFileSize
new1.12 KB
PASSED: [[SimpleTest]]: [MySQL] 33,445 pass(es).
[ View ]

I put myself in the shoes of who might be reading it with no past knowledge (in fact, that's me). Then, I decided to get rid of "during form validation." to avoid misleading.

I feel I like learning about the API sending patches.

StatusFileSize
new1.2 KB
PASSED: [[SimpleTest]]: [MySQL] 33,451 pass(es).
[ View ]

wrong path sent in #30
sending the correct one

This looks quite reasonable to me. Any comments sun?

Status:Needs review» Reviewed & tested by the community

Thanks!

Looks good.

Status:Reviewed & tested by the community» Fixed

Committed and pushed to 8.x and 7.x. Thanks!

Status:Fixed» Closed (fixed)
Issue tags:-Novice, -needs backport to D7

Automatically closed -- issue fixed for 2 weeks with no activity.