在PHP开发中,生成符合特定DTD的XML需要先明确目标DTD的结构规则,再选择合适的工具按照规则拼接或生成XML内容,最后通过校验确保输出结果符合规范。

明确目标DTD规则
首先需要根据需求确定DTD的具体内容,比如我们定义一个简单的用户数据DTD,规则如下:
<!ELEMENT users (user+)> <!ELEMENT user (name,age,email)> <!ATTLIST user id CDATA #REQUIRED> <!ELEMENT name (#PCDATA)> <!ELEMENT age (#PCDATA)> <!ELEMENT email (#PCDATA)>
这个DTD规定了根节点是users,包含至少一个user子节点,每个user需要有必填的id属性,以及name、age、email三个子元素,子元素内容都是文本类型。
使用XMLWriter生成合规XML
XMLWriter是PHP内置的流式XML生成工具,适合生成大型XML文件,我们可以按照DTD规则逐步写入内容:
<?php
// 创建XMLWriter实例
$writer = new XMLWriter();
// 打开内存输出,也可以直接输出到文件
$writer->openMemory();
// 设置缩进,让生成的XML更易读
$writer->setIndent(true);
// 开始文档,指定版本和编码
$writer->startDocument('1.0', 'UTF-8');
// 写入DTD声明,对应我们之前定义的DTD规则
$writer->writeDTD('users', null, null, '
<!ELEMENT users (user+)>
<!ELEMENT user (name,age,email)>
<!ATTLIST user id CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT email (#PCDATA)>
');
// 开始根节点users
$writer->startElement('users');
// 第一个user节点
$writer->startElement('user');
$writer->writeAttribute('id', '1001');
$writer->writeElement('name', '张三');
$writer->writeElement('age', '25');
$writer->writeElement('email', 'zhangsan@ipipp.com');
$writer->endElement(); // 结束user节点
// 第二个user节点
$writer->startElement('user');
$writer->writeAttribute('id', '1002');
$writer->writeElement('name', '李四');
$writer->writeElement('age', '28');
$writer->writeElement('email', 'lisi@ipipp.com');
$writer->endElement(); // 结束user节点
$writer->endElement(); // 结束users节点
$writer->endDocument(); // 结束文档
// 输出生成的XML内容
echo $writer->outputMemory();
?>
运行上述代码后,会生成包含DTD声明的XML,结构完全符合我们定义的DTD规则。
使用SimpleXML生成合规XML
SimpleXML适合处理结构简单的XML,生成方式更直观,同样可以嵌入DTD声明:
<?php
// 创建根节点users
$xml = new SimpleXMLElement('<users/>');
// 添加第一个user节点,设置id属性
$user1 = $xml->addChild('user');
$user1->addAttribute('id', '1001');
$user1->addChild('name', '张三');
$user1->addChild('age', '25');
$user1->addChild('email', 'zhangsan@ipipp.com');
// 添加第二个user节点
$user2 = $xml->addChild('user');
$user2->addAttribute('id', '1002');
$user2->addChild('name', '李四');
$user2->addChild('age', '28');
$user2->addChild('email', 'lisi@ipipp.com');
// 获取XML字符串
$xmlString = $xml->asXML();
// 在XML开头插入DTD声明
$dtd = '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE users [
<!ELEMENT users (user+)>
<!ELEMENT user (name,age,email)>
<!ATTLIST user id CDATA #REQUIRED>
<!ELEMENT name (#PCDATA)>
<!ELEMENT age (#PCDATA)>
<!ELEMENT email (#PCDATA)>
]>';
// 替换默认的开头声明,拼接DTD
$finalXml = str_replace('<?xml version="1.0" encoding="UTF-8"?>', $dtd, $xmlString);
echo $finalXml;
?>
这种方式生成的XML同样符合DTD要求,不过需要注意拼接DTD时的格式正确性。
校验生成的XML是否符合DTD
生成XML后,我们可以通过DOMDocument进行DTD校验,确保内容合规:
<?php
// 假设$finalXml是之前生成的带DTD的XML字符串
$dom = new DOMDocument();
// 加载XML内容
$dom->loadXML($finalXml);
// 进行DTD校验
if ($dom->validate()) {
echo 'XML符合DTD规范';
} else {
echo 'XML不符合DTD规范';
}
?>
如果生成的XML结构不符合DTD规则,比如缺少必填属性、子元素顺序错误,校验都会返回失败,开发者可以根据错误提示调整生成逻辑。
注意事项
- 写入DTD时要保证规则和预设完全一致,尤其是元素嵌套关系、属性要求不能出错
- 如果XML内容包含特殊字符,比如
<、>、&,需要提前做转义处理,避免破坏XML结构 - 生成大型XML文件时优先选择XMLWriter,内存占用更低,性能更好
- 校验环节不能省略,尤其是在数据来源不可控的场景下,避免输出不符合规范的XML