PHP 如何插入嵌套元素 Libreoffice 样式

Posted

技术标签:

【中文标题】PHP 如何插入嵌套元素 Libreoffice 样式【英文标题】:PHP How To Insert Nested Elements Libreoffice Style 【发布时间】:2018-12-23 10:00:51 【问题描述】:

Libreoffice 将 Writer 文档内容存储在 XML 格式的文件中。在 php 中,我想将具有不同格式的文本插入到文本段落中。不幸的是,Libreoffice 在另一个元素的文本中使用嵌套元素来做到这一点。这是一个简化的示例:

<text:p text:style-name="P1">

   the quick brown
        <text:span text:style-name="T1"> fox jumps over</text:span>      
   the lazy dog

</text:p>

我没有发现 PHP 中的 SimpleXML 或 XML DOM 函数可以让我在另一个元素的文本中插入一个新元素,就像这里需要的那样。我在这里忽略了什么吗?

【问题讨论】:

【参考方案1】:

SimpleXML 不能很好地处理混合子节点,但在 DOM 中并不难,只是有点冗长。请记住,在 DOM 中,任何东西都是节点,而不仅仅是元素。因此,您要做的是用三个新节点替换单个文本节点 - 一个文本节点、新元素节点和另一个文本节点。

$xmlns = [
  'text' => 'urn:oasis:names:tc:opendocument:xmlns:text:1.0'
];

$xml = <<<'XML'
<text:p 
   text:style-name="P1" 
   xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0">
   the quick brown fox jumps over the lazy dog
</text:p>
XML;

$document = new DOMDocument();
$document->loadXML($xml);
$xpath = new DOMXpath($document);

$searchFor = 'fox jumps over';

// iterate over text nodes containing the search string
$expression = '//text:p//text()[contains(., "'.$searchFor.'")]';
foreach ($xpath->evaluate($expression) as $textNode) 
    // split the text content at the search string and capture any part
    $parts = preg_split(
        '(('.preg_quote($searchFor).'))', 
        $textNode->textContent, 
        -1, 
        PREG_SPLIT_DELIM_CAPTURE
    );
    // here should be at least two parts
    if (count($parts) < 2) 
        continue;
    
    // fragments allow to treat several nodes like one
    $fragment = $document->createDocumentFragment();
    foreach ($parts as $part) 
        // matched the text
        if ($part === $searchFor) 
            // create the new span
            $fragment->appendChild(
                $span = $document->createElementNS($xmlns['text'], 'text:span')
            );
            $span->setAttributeNS($xmlns['text'], 'text:style-name', 'T1');
            $span->appendChild($document->createTextNode($part));
         else 
            // add the part as a new text node
            $fragment->appendChild($document->createTextNode($part));
           
    
    // replace the text node with the fragment
    $textNode->parentNode->replaceChild($fragment, $textNode);


echo $document->saveXML();

【讨论】:

刚刚试一试,它就像一个魅力!现在到了很难理解细节的部分!非常感谢!!!

以上是关于PHP 如何插入嵌套元素 Libreoffice 样式的主要内容,如果未能解决你的问题,请参考以下文章

LibreOffice 如何恢复当前元素

如何将嵌套的子表值与父表行关联并插入子表值对应于php中的父表行

Java Open\LibreOffice 在 odt 中插入文件\对象

如何插入数据 url/二进制文件以替换 libreoffice writer 文档中的图像?

如何在 libreoffice calc 中编写 python 宏以在插入外部数据时处理合并的单元格

如何按嵌套在其中的元素对 PHP 数组进行排序?