Forum


Replies: 1   Views: 2528
Variable2text improvement
Topic closed:
Please note this is an old forum thread. Information in this post may be out-to-date and/or erroneous.
Every phpdocx version includes new features and improvements. Previously unsupported features may have been added to newer releases, or past issues may have been corrected.
We encourage you to download the current phpdocx version and check the Documentation available.

Posted by lharkleroad  · 17-03-2016 - 21:29

If your document template contains variables in form elements, replacing those variables replaces the text entered into the field, but it does not replace the default value. This can cause problems if the document needs to be edited after it is created because the copied and pasted field will show the default value instead of the text that was entered into it. To preserve the text, we need to replace the default value, too.

To fix this, variable2Text can be modified as follows:

1. Change the xpath query to include form field default values.

$query = '//w:default[@w:val[contains(.,"' . $search . '")]]|//w:t[text()[contains(., "' . $search . '")]]';

2. Set the defalut value if the attribute exists in your matching node. Otherwise, replace the node's text value as usual.

if (!empty($node->attributes('w', TRUE)->val)) {
        $node->attributes('w', TRUE)->val = $val;
} else {
        $strNode = str_replace($search, $val, $strNode);
        $node[0] = $strNode;
}

Here is the complete method with the above modifications.

    private function variable2Text($variables, $loadContent, $options)
    {
        if (isset($options['firstMatch'])) {
            $firstMatch = $options['firstMatch'];
        } else {
            $firstMatch = false;
        }
        if (!self::$_preprocessed) {
            $loadContent = $this->repairVariables($variables, $loadContent);
        }
        $dom = simplexml_load_string($loadContent);
        $dom->registerXPathNamespace('w', 'http://schemas.openxmlformats.org/wordprocessingml/2006/main');
        foreach ($variables as $var => $val) {
            $search = self::$_templateSymbol . $var . self::$_templateSymbol;
            $query = '//w:default[@w:val[contains(.,"' . $search . '")]]|//w:t[text()[contains(., "' . $search . '")]]';
            if ($firstMatch) {
                $query = '(' . $query . ')[1]';
            }
            $foundNodes = $dom->xpath($query);
            foreach ($foundNodes as $node) {
                $strNode = (string) $node;
                if (isset($options['parseLineBreaks']) && $options['parseLineBreaks']) {
                    $domNode = dom_import_simplexml($node);
                    //parse $val for \n\r, \r\n, \n or \r
                    $val = str_replace(array('\n\r', '\r\n', '\n', '\r'), '<linebreak/>', $val);
                    $strNode = str_replace($search, $val, $strNode);
                    $runs = explode('<linebreak/>', $strNode);
                    $preserveWS = false;
                    $preserveWhiteSpace = $domNode->getAttribute('xml:space');
                    if ($preserveWhiteSpace == 'preserve') {
                        $preserveWS = true;
                    }
                    //TODO: check and finish
                    $numberOfRuns = count($runs);
                    $counter = 0;
                    foreach ($runs as $run) {
                        $counter++;
                        $newT = $domNode->ownerDocument->createElementNS('http://schemas.openxmlformats.org/wordprocessingml/2006/main', 't', htmlspecialchars($run));
                        if ($preserveWS) {
                            $newT->setAttribute('xml:space', 'preserve');
                        }
                        $domNode->parentNode->insertBefore($newT, $domNode);
                        if ($counter < $numberOfRuns) {
                            $br = $domNode->ownerDocument->createElementNS('http://schemas.openxmlformats.org/wordprocessingml/2006/main', 'br');
                            $domNode->parentNode->insertBefore($br, $domNode);
                        }
                    }
                    $domNode->parentNode->removeChild($domNode);
                } else {
                    if (!empty($node->attributes('w', TRUE)->val)) {
                        $node->attributes('w', TRUE)->val = $val;
                    } else {
                        $strNode = str_replace($search, $val, $strNode);
                        $node[0] = $strNode;
                    }
                }
            }
        }

        return $dom;
    }

 

Posted by admin  · 18-03-2016 - 07:37

Hello,

Thanks for your suggestion, we're going to check it. In the current dev branch we have a new implementation to allow raw replacements, this is changing any string in the main document, headers, footers, comments, footnotes and endnotes.

It's a very generic method and allows to change attributes, default form values and almost any other string in XML. It'll be released within the next version of phpdocx.

Regards.