You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在不破坏HTML标签的情况下实现PHP西里尔字母转拉丁字母?

如何在不破坏HTML标签的前提下转写西里尔字母为拉丁字母

嘿,这个问题我太懂了!很多人一开始会直接用全局字符串替换,结果把HTML标签里的字符也搞砸了——就像你举的例子里,<p>的p会被当成西里尔的п替换掉,完全破坏了结构。核心思路其实很简单:只针对HTML里的纯文本内容做转写,跳过标签本身。下面给你两种靠谱的PHP实现方案,对应不同场景:

方法一:用DOMDocument精准处理文本节点(最稳妥)

这种方法借助PHP的DOM解析能力,能准确区分HTML标签和文本节点,绝对不会碰标签里的内容,适合复杂HTML场景。

完整代码示例

// 定义完整的西里尔-拉丁转写映射(覆盖大小写和特殊字符)
$cyrToLatMap = [
    'а' => 'a', 'б' => 'b', 'в' => 'v', 'г' => 'g', 'д' => 'd', 'е' => 'e', 'ё' => 'yo', 'ж' => 'zh',
    'з' => 'z', 'и' => 'i', 'й' => 'y', 'к' => 'k', 'л' => 'l', 'м' => 'm', 'н' => 'n', 'о' => 'o',
    'п' => 'p', 'р' => 'r', 'с' => 's', 'т' => 't', 'у' => 'u', 'ф' => 'f', 'х' => 'h', 'ц' => 'ts',
    'ч' => 'ch', 'ш' => 'sh', 'щ' => 'sht', 'ъ' => '', 'ы' => 'y', 'ь' => '', 'э' => 'e', 'ю' => 'yu',
    'я' => 'ya',
    'А' => 'A', 'Б' => 'B', 'В' => 'V', 'Г' => 'G', 'Д' => 'D', 'Е' => 'E', 'Ё' => 'Yo', 'Ж' => 'Zh',
    'З' => 'Z', 'И' => 'I', 'Й' => 'Y', 'К' => 'K', 'Л' => 'L', 'М' => 'M', 'Н' => 'N', 'О' => 'O',
    'П' => 'P', 'Р' => 'R', 'С' => 'S', 'Т' => 'T', 'У' => 'U', 'Ф' => 'F', 'Х' => 'H', 'Ц' => 'Ts',
    'Ч' => 'Ch', 'Ш' => 'Sh', 'Щ' => 'Sht', 'Ъ' => '', 'Ы' => 'Y', 'Ь' => '', 'Э' => 'E', 'Ю' => 'Yu',
    'Я' => 'Ya'
];

// 递归遍历DOM节点,只处理文本节点
function transliterateTextNodes($node, $map) {
    // 只处理纯文本节点
    if ($node->nodeType === XML_TEXT_NODE) {
        $node->nodeValue = strtr($node->nodeValue, $map);
    }
    // 递归处理所有子节点
    if ($node->hasChildNodes()) {
        foreach ($node->childNodes as $child) {
            transliterateTextNodes($child, $map);
        }
    }
}

// 示例使用
$html = '<title>Главная страница</title><p>Кирилица и <b>жирный текст</b></p>';

// 初始化DOMDocument,处理UTF-8编码避免乱码
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8'));

// 转写所有文本节点
transliterateTextNodes($dom->documentElement, $cyrToLatMap);

// 输出结果,移除DOM自动添加的html/body标签
$result = $dom->saveHTML();
$result = preg_replace('/^<!DOCTYPE.*?>|<html.*?>|<body.*?>|<\/body>|<\/html>/i', '', $result);
echo trim($result);

效果说明

运行后会输出:

<title>Glavnaja stranica</title><p>Kirilitca i <b>jirnyj tekst</b></p>

可以看到,所有文本内容都转写了,但<title>、<p>、<b>这些标签完全没被改动。

方法二:正则表达式快速实现(适合简单HTML)

如果你处理的HTML结构比较简单(没有复杂嵌套或特殊字符),用正则匹配标签间的文本内容也是个快速方案。

代码示例

$cyrToLatMap = [/* 同上的转写映射数组 */];

$html = '<title>Главная страница</title><p>Кирилица и <b>жирный текст</b></p>';

// 匹配标签之间的文本内容,然后转写
$result = preg_replace_callback('/>([^<]+)</', function($matches) use ($cyrToLatMap) {
    // $matches[1]是标签之间的纯文本
    return '>' . strtr($matches[1], $cyrToLatMap) . '<';
}, $html);

echo $result;

注意事项

  • 这个方法的局限性是:如果HTML里有标签嵌套过深、或者文本里包含</>的实体(比如&lt;),正则可能会匹配出错。
  • 只推荐用于结构简单的HTML片段。

额外提示

  • 转写映射可以根据你的需求调整,比如有些转写规则会把ё写成e,或者щ写成shch,直接修改数组里的对应值就行。
  • 确保你的HTML是UTF-8编码,不然转写时容易出现乱码问题。

内容的提问来源于stack exchange,提问作者Nuriddin Rashidov

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:24:26