XML严禁 & < ,建议 < > & ' “进行转义

XML中预定义了5个实体引用: < > & ' “

其中,'<' 和 '&' 是非法的。

'<' 会产生错误,因为解析器会把该字符解释为新元素的开始。

'&' 也会产生错误,因为解析器会把该字符解释为字符实体的开始。

其它实体虽然都是合法的,但是把它们替换为实体是个好的习惯。

CDATA区段中值的限制

CDATA区段由 '' 结束.因此,CDATA的值不能包含']]>',否则XML解析器会提前闭合CDATA,导致解析错误.而结尾的']]>'闭合也不能包含空格或者折行.

<![CDATA[ value ]]> ]]> //值包含']]>',非法
<![CDATA[ value ] ] > //结尾的']]>'包含空格,非法
<![CDATA[ value ]]> //合法

SimpleXML类生成带有CDATA区段的值

SimpleXML类如其名字,因为其简单那易用性,得到一部分程序员的青睐,但是其本身却不支持生成带有CDATA区段的值.是不是为了生成CDATA区段的值就要放弃SimpleXML类了呢?

谷歌到一种解决方案

class SimpleXMLExtended extends SimpleXMLElement
{
public function addCData($cdata_text)
{
$node = dom_import_simplexml($this);
$no = $node->ownerDocument;
$node->appendChild($no->createCDATASection($cdata_text));
}
}
$xmlFile = 'config.xml';
// instead of $xml = new SimpleXMLElement('<sites/>');
$xml = new SimpleXMLExtended('<sites/>');
$site = $xml->addChild('site');
// instead of $site->addChild('site', 'Site Title');
$site->title = NULL; // VERY IMPORTANT! We need a node where to append
$site->title->addCData('Site Title');
$site->title->addAttribute('lang', 'en');
$xml->asXML($xmlFile);

此类继承自SimpleXMLElement类,通过添加addCData方法,利用DOMDocument和SimpleXML的互通性,把SimpleXML对象转换成DOM元素对象,利用DOM元素对象节点可以创建CDATA区段值的特点完成操作.

此类虽然解决了SimpleXML不能创建CDATA区段值的缺点,但是代码不够简洁--每次都要在设置值之前都要先将值设置为NULL,而此方法又是必须的,否则会报错.

因此我对此类进行了再次封装,调用起来更加简洁,代码如下:

class SimpleXMLExtended extends SimpleXMLElement
{
public function addCData($data)
{
$node = dom_import_simplexml($this);
$no = $node->ownerDocument;
$node->appendChild($no->createCDATASection($data));
} public function addNode($key,$value=''){
if($value === '') $value = ' ';
$this->$key = NULL;
$this->$key->addCData($value);
}
} //调用更加简洁
$xml = new SimpleXMLElement('<?xml version="1.0"?><DOCUMENT></DOCUMENT>');
$xml->addChild('item');//向XML节点添加一个子节点item
$item->addNode('key','value');//向item节点添加一个键为"key",CDATA区段值为"value"

UTF-8编码下提示非UTF-8字符

XML中编码全是UTF-8,怎么会有非UTF-8字符呢?通过浏览器查看源码,也没发现非法字符.

问大神同事,得到了'没遇到过'的答案.

然后就想着把报错的数据字段从数据库里复制出来,看一下结果.从库中复制到了sublime中,然后看到如下图的'FS'字符

好端端的内容,为啥会产生一个'FS'呢?然后谷歌,终于找到了答案.原来该特殊字符叫'控制字符',想要了解控制字符的同学可以看关于控制字符的定义.

当时解决方法简直简单粗暴,手动删掉,然后回存到数据库:

后来领导也遇到相似的问题,我告诉他是有可能是控制字符造成的,然后他给了我一个函数,可以过滤掉控制字符.函数如下:

function strip_control_characters($string){
return preg_replace('/[\x00-\x1F\x7F-\x9F]/u', '', $string);
}

**PS: 此函数需要编码为UTF-8才可以过滤掉. **

XML读取的字段中包含'-',要用'{}'把字段包裹

$arr = array('a-b-c'=>'abc');
$obj = (object)($arr);
//如何获取'a-b-c'字段的值? echo $obj->a-b-c;//报错
echo $obj->'a-b-c';//报错
echo $obj->{'a-b-c'};//正常

** 此注意点可以总结为PHP在获取对象的key中包含'-',要用'{}'包住 **

SimpleXML的节点值要强转成字符型后再比较

$string = <<<XML
&lt;?xml version='1.0'?&gt;
&lt;document&gt;
&lt;title&gt;Dear Jane&lt;/title&gt;
&lt;from&gt;Joe&lt;/from&gt;
&lt;to&gt;Jane&lt;/to&gt;
&lt;body&gt;
Dear Jane:
I love U,can you be my girlfriend?
yours Joe
&lt;/body&gt;
&lt;/document&gt;
XML; $email = simplexml_load_string($string); //Joe发送邮件,但是忘记收件人是否是女神Jane if($email->to == 'Jane'){
echo 'Good Job';
}else{
echo 'I am in troblem!';
}

得到的答案是'I am in troblem!'

原来'$email->to'得到的值的类型为SimpleXMLElement对象,

非字符串,非数组.

因此,一定要强制转换成'string'类型后在比较.

XML调试

因为SimpleXML类和DOMDocument类都是基于libxml扩展开发的,开发过程中,可以使用libxml_use_internal_errors调试.

此函数有一个参数,默认为false,即禁用用户错误处理.true为开启用户错误处理.

libxml_use_internal_errors(true);
$sxe = simplexml_load_string("<?xml version='1.0'><broken><xml></broken>");
if ($sxe === false) {
echo "Failed loading XML\n";
foreach(libxml_get_errors() as $error) {
echo "\t", $error->message;
}
}

以上代码输出:

Failed loading XML

Blank needed here

parsing XML declaration: '?>' expected

Opening and ending tag mismatch: xml line 1 and broken

Premature end of data in tag broken line 1

通过错误处理,知道原来有两个错误:

  1. 声明少写一个 '?>'

  2. xml标签没有闭合

XML中的值得注意的"坑"的更多相关文章

  1. IDEA中写MyBatis的xml配置文件编译报错的坑

    IDEA中写MyBatis的xml配置文件编译报错的坑 说明:用IDEA编译工具在项目中使用Mybatis框架,编写mybatis-config.xml和Mapper.xml配置文件时,编译项目出现错 ...

  2. Odoo “坑” 系列之 XML中的布尔类型

    在Odoo中试图通过XML方式更新某条Record的值,却意外发现根本不能更新,经查,对于XML中Boolean类型的字段,更新的方式应该采用eval的方式.

  3. Android XML中引用自定义内部类view的四个why

    今天碰到了在XML中应用以内部类形式定义的自定义view,结果遇到了一些坑.虽然通过看了一些前辈写的文章解决了这个问题,但是我看到的几篇都没有完整说清楚why,于是决定做这个总结. 使用自定义内部类v ...

  4. xml解析、写入遇到的坑

    前言 最近在看一个线上xml文件导出的问题,需求如下: 从我们平台导出一个后缀为tmx的术语语料数据(实际内容为xml文件),然后导入到其他第三方平台发现无法导入. 从其他平台导入的tmx文件无法导入 ...

  5. mapper.xml中转义

    1.用转义字符转义 XML转义字符 < < 小于号 > > 大于号 & & 和 &apos; ’ 单引号 " " 双引号 <i ...

  6. xml中的<![CDATA[]]> 简介

    被<![CDATA[]]>这个标记所包含的内容将表示为纯文本,比如<![CDATA[<]]>表示文本内容“<”.  此标记用于xml文档中,我们先来看看使用转义符的 ...

  7. Android中点击按钮获取string.xml中内容并弹窗提示

    场景 AndroidStudio跑起来第一个App时新手遇到的那些坑: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103797 ...

  8. xml中的<![CDATA[]]>和转义字符

    被<![CDATA[]]>这个标记所包含的内容将表示为纯文本,比如<![CDATA[<]]>表示文本内容"<". 此标记用于xml文档中,我们先 ...

  9. web.xml中welcome-file-list的作用

    今天尝试使用struts2+ urlrewrite+sitemesh部署项目,结果发现welcome-file-list中定义的欢迎页不起作用: <welcome-file-list> & ...

随机推荐

  1. python基础之基础数据类型1

    int 整形 数字用于计算和比较 python3没有long,python2有整形和长整型 十进制二进制转换方法 bin(10进制) ==二进制 0b(二进制) int("二进制" ...

  2. spark性能调优01-常规调优

    1.分配更多的资源 1.1 分配的资源有:executor.cup per executor.memory per executor.driver memory 1.2 如何分配:在spark-sub ...

  3. ollvm 编译

    ollvm 的编译相对 llvm 更简单, 1:下载ollvm代码,去 https://github.com/obfuscator-llvm/obfuscator/tree/llvm-4.0 下载,并 ...

  4. sleep()方法和wait()方法的区别? sleep()方法和yield()方法的区别?

    sleep()方法和wait()方法的区别? sleep方法是Thread的静态方法,wait方法是Object类的普通方法 sleep方法不释放同步锁,wait方法释放同步锁(执行notify方法唤 ...

  5. springboot整合RocketMq(非事务)

    1.配置文件 1.yml配置文件 rocketmq: #mq配置 producer: iseffect: true type: default # (transaction,default) tran ...

  6. 《构建之法》IT行业的创新 读书笔记 WEEK 5

    本周选读邹欣老师的<构建之法>第16章——IT行业的创新. 邹欣老师将本章话题分成五个部分来阐述:创新的迷思.创新的时机.创新的招数.魔方的创新.创新和作坊,博主认为时机和招数这两个部分在 ...

  7. easyui grid单元格类型

    在实际应用中可能会碰到不同的需求,比如会根据每行不同的参数或属性设置来设置同列不同的editor类型,这时原有的例子就显的有点太过简单,不能实现我们的需求,现在应用我在项目中的操作为例,显示下实现同列 ...

  8. 【最新】docker 安装elasticsearch + kibana步骤【第一篇_elasticsearch】

     最近在用docker 安装elasticsearch + kibana 遇到了很多坑,最后成功安装elasticsearch + kibana (6.8.1)版本   安装了一下午,现总结过程中遇到 ...

  9. 关于KiCAD

    关于KiCAD 使用背景 一直以来公司都在用AD作为EDA软件,但是最近公司频繁收到律师函,所以决定找一款开源的软件来代替AD,目前市场上开源的只找到了KiCAD和Easy EDA(中文版立创EDA) ...

  10. hbase报错: hbase.PleaseHoldException: Master is initializing

    查看hbase服务状态报错:   hbase(main)::> status ERROR: org.apache.hadoop.hbase.PleaseHoldException: Master ...