如何实现嵌套DVI到table包括class到样式的代码转换?
How to realize a code conversion from nested DVIs to table including class to style?
情况如下:
我想将嵌套的 DIV 元素更改为 table 元素,我希望将 类 设置为内联样式。
我现在有一个带有 类 和样式属性的示例数组:
$classes = array(
'container' => 'width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;',
'card' => 'position: relative;display: -ms-flexbox;display: flex;-ms-flex-direction: column;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.125);border-radius: 0.25rem;',
);
此代码将转换为以下代码:
<div class="container">
01
<div class="card">
02
</div>
</div>
此代码将由此创建:
<table>
<tr>
<td class="container" style="width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;">
01
<table>
<tr>
<td class="card" style="position: relative;display: -ms-flexbox;display: flex;-ms-flex-direction: column;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.125);border-radius: 0.25rem;">
02
</td>
</tr>
</table>
</td>
</tr>
</table>
有人知道我怎么能做这样的事情吗?
自周五以来,我一直在试验 preg_replace_callback 和 DOMDocument。不幸的是一切都没有成功。
没什么特别的。您需要注意的是:
- 以相反的顺序替换节点
- 使用子节点的深拷贝(使用
DOMNode::cloneNode
,参数设置为true
)
我假设您正在使用 html 的部分内容(不是带有 <html>
和 <body>
标签的完整文档),但如果不是这样,您可以轻松更改自己的代码:
$cssClasses = [
'container' => 'width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;',
'card' => 'position: relative;display: -ms-flexbox;display: flex;-ms-flex-direction: column;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.125);border-radius: 0.25rem;'
];
$html = <<<'EOD'
<div class="container">
01
<div class="card">
02
</div>
</div>
EOD;
$dom = new DOMDocument;
$dom->loadHTML($html);
$divNL = $dom->getElementsByTagName('div');
for ($i = $divNL->length - 1; $i >= 0; $i--) {
$node = $divNL->item($i);
$table = $dom->createElement('table');
$tr = $dom->createElement('tr');
$td = $dom->createElement('td');
$table->appendChild($tr);
$tr->appendChild($td);
foreach ($node->attributes as $attr) {
$td->appendChild($attr);
}
$styles = array_reduce(
preg_split('~\s+~u', $td->getAttribute('class')),
function($c, $i) use ($cssClasses) {
return isset($cssClasses[$i]) ? $cssClasses[$i] . $c : $c;
},
$td->getAttribute('style')
);
if ( !empty($styles) )
$td->setAttribute('style', $styles);
foreach ($node->childNodes as $childNode) {
$td->appendChild($childNode->cloneNode(true));
}
$node->parentNode->replaceChild($table, $node);
}
$result = '';
foreach ($dom->getElementsByTagName('body')->item(0)->childNodes as $childNode) {
$result .= $dom->saveHTML($childNode);
}
echo $result;
情况如下: 我想将嵌套的 DIV 元素更改为 table 元素,我希望将 类 设置为内联样式。
我现在有一个带有 类 和样式属性的示例数组:
$classes = array(
'container' => 'width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;',
'card' => 'position: relative;display: -ms-flexbox;display: flex;-ms-flex-direction: column;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.125);border-radius: 0.25rem;',
);
此代码将转换为以下代码:
<div class="container">
01
<div class="card">
02
</div>
</div>
此代码将由此创建:
<table>
<tr>
<td class="container" style="width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;">
01
<table>
<tr>
<td class="card" style="position: relative;display: -ms-flexbox;display: flex;-ms-flex-direction: column;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.125);border-radius: 0.25rem;">
02
</td>
</tr>
</table>
</td>
</tr>
</table>
有人知道我怎么能做这样的事情吗? 自周五以来,我一直在试验 preg_replace_callback 和 DOMDocument。不幸的是一切都没有成功。
没什么特别的。您需要注意的是:
- 以相反的顺序替换节点
- 使用子节点的深拷贝(使用
DOMNode::cloneNode
,参数设置为true
)
我假设您正在使用 html 的部分内容(不是带有 <html>
和 <body>
标签的完整文档),但如果不是这样,您可以轻松更改自己的代码:
$cssClasses = [
'container' => 'width: 100%;padding-right: 15px;padding-left: 15px;margin-right: auto;margin-left: auto;',
'card' => 'position: relative;display: -ms-flexbox;display: flex;-ms-flex-direction: column;flex-direction: column;min-width: 0;word-wrap: break-word;background-color: #fff;background-clip: border-box;border: 1px solid rgba(0, 0, 0, 0.125);border-radius: 0.25rem;'
];
$html = <<<'EOD'
<div class="container">
01
<div class="card">
02
</div>
</div>
EOD;
$dom = new DOMDocument;
$dom->loadHTML($html);
$divNL = $dom->getElementsByTagName('div');
for ($i = $divNL->length - 1; $i >= 0; $i--) {
$node = $divNL->item($i);
$table = $dom->createElement('table');
$tr = $dom->createElement('tr');
$td = $dom->createElement('td');
$table->appendChild($tr);
$tr->appendChild($td);
foreach ($node->attributes as $attr) {
$td->appendChild($attr);
}
$styles = array_reduce(
preg_split('~\s+~u', $td->getAttribute('class')),
function($c, $i) use ($cssClasses) {
return isset($cssClasses[$i]) ? $cssClasses[$i] . $c : $c;
},
$td->getAttribute('style')
);
if ( !empty($styles) )
$td->setAttribute('style', $styles);
foreach ($node->childNodes as $childNode) {
$td->appendChild($childNode->cloneNode(true));
}
$node->parentNode->replaceChild($table, $node);
}
$result = '';
foreach ($dom->getElementsByTagName('body')->item(0)->childNodes as $childNode) {
$result .= $dom->saveHTML($childNode);
}
echo $result;