我目前正在重写一个PHP类,该类试图将XML文件拆分为更小的块,以使用XMLReader和XMLWriter,而不是当前的基本文件系统和正则表达式方法。
但是,我不知道如何从XML前导中获取版本、编码和独立标志。
我的测试XML文件的开头如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fakedoctype SYSTEM "fake_doc_type.dtd">
<!--
This is a comment, it's here to try and get the parser to break in some way
-->
<root attribute="value" otherattribute="othervalue">
我可以用read()、next()等打开文档,但我似乎无法得到
我的测试代码如下:
$a = new XMLReader ();
var_dump ($a -> open ('/path/to/test/file.xml')) // true
var_dump ($a -> nodeType); // 0
var_dump ($a -> name); // ""
var_dump ($a -> readOuterXML ()); // ''
var_dump ($a -> read ()); // true
var_dump ($a -> nodeType); // 10
var_dump ($a -> readOuterXML ()); // <!DOCTYPE fakedoctype SYSTEM "fake_doc_type.dtd">
当然,我可以总是假设XML 1.0,编码UTF8,standalone=yes,但为了正确起见,我真的希望能够获取源提要中的值,并在生成拆分文件时使用它们。
关于XMLReader和XMLwriter的文档似乎很差,所以我很可能错过了文档中的一些内容。有人知道在这种情况下该怎么办吗?
我从XMLReader
中了解到,即使它有XMLReader::XML_声明
常量,但在使用XMLReader::$nodeType
属性中的XMLReader::read()
遍历文档时,我从未体验过它。
看起来它被跳过了,我还想知道为什么会这样,我还没有找到任何标志或选项来改变这种行为。
对于输出,XMLReader
总是返回UTF-8编码的字符串。这与PHP中其他基于libxml的部分相同。所以从这方面来看,一切都很清楚。但我假设这不是您感兴趣的部分,而是您使用XMLReader打开的文件中的具体字符串输入::open()
。
不是专门针对XMLReader
的,我曾经创建了一个名为XMLRecoder
的实用程序类,它能够基于XML声明和BOM检测XML字符串的编码。我认为你应该两者都做。这是我认为您仍然需要使用正则表达式的一部分,但由于XML声明必须是第一件事,而且它是一个定义非常好和严格的处理指令(PI),您应该能够在其中窥探。
这是xmlrecord
代码中的一些相关部分:
### excerpt from https://gist.github.com/hakre/5194634
/**
* pcre pattern to access EncodingDecl, see <http://www.w3.org/TR/REC-xml/#sec-prolog-dtd>
*/
const DECL_PATTERN = '(^<\?xml\s+version\s*=\s*(["\'])(1\.\d+)\1\s+encoding\s*=\s*(["\'])(((?!\3).)*)\3)';
const DECL_ENC_GROUP = 4;
const ENC_PATTERN = '(^[A-Za-z][A-Za-z0-9._-]*$)';
...
($result = preg_match(self::DECL_PATTERN, $buffer, $matches, PREG_OFFSET_CAPTURE))
&& $result = $matches[self::DECL_ENC_GROUP];
如图所示,它一直持续到编码,所以它并不完整。然而,对于提取编码的需求(以及您的需求版本),它应该完成这项工作。我对大量(数千)随机XML文档进行了测试。
另一部分是BOM检测:
### excerpt from https://gist.github.com/hakre/5194634
const BOM_UTF_8 = "\xEF\xBB\xBF";
const BOM_UTF_32LE = "\xFF\xFE\x00\x00";
const BOM_UTF_16LE = "\xFF\xFE";
const BOM_UTF_32BE = "\x00\x00\xFE\xFF";
const BOM_UTF_16BE = "\xFE\xFF";
...
/**
* @param string $string string (recommended length 4 characters/octets)
* @param string $default (optional) if none detected what to return
* @return string Encoding, if it can not be detected defaults $default (NULL)
* @throws InvalidArgumentException
*/
public function detectEncodingViaBom($string, $default = NULL)
{
$len = strlen($string);
if ($len > 4) {
$string = substr($string, 0, 4);
} elseif ($len < 4) {
throw new InvalidArgumentException(sprintf("Need at least four characters, %d given.", $len));
}
switch (true) {
case $string === self::BOM_UTF_16BE . $string[2] . $string[3]:
return "UTF-16BE";
case $string === self::BOM_UTF_8 . $string[3]:
return "UTF-8";
case $string === self::BOM_UTF_32LE:
return "UTF-32LE";
case $string === self::BOM_UTF_16LE . $string[2] . $string[3]:
return "UTF-16LE";
case $string === self::BOM_UTF_32BE:
return "UTF-32BE";
}
return $default;
}
使用BOM检测时,我也对同一组XML文档运行了此功能,但是,使用BOM的文档并不多。如您所见,检测顺序针对更常见的场景进行了优化,同时考虑了不同BOM之间的重复二进制模式。我遇到的大多数文档都没有BOM,您主要需要它来确定文档是否是UTF-32编码的。
希望这至少能提供一些见解。
通过sdk.js文件内容查看版本 sdk.js中的文件头部含有该文件的信息,其中v{1.2.1}中的1.2.1为当前文件的版本。 /*! * sdk.js v1.2.1 * 2017-10-26 15:13:33 * (c) 2017 mudu.tv * 杭州雅顾科技有限公司 版权所有 * */ 通过接口获取 // 返回string, 如: 1.2.1 var version =
/** 获取SDK版本号 @return 版本号 */ NSString *version = [Ntalker ntalker_versionNumber];
cmf_version() 5.1.0&5.0.190111增加 功能 获取 ThinkCMF版本号 参数 无 返回 string
var_dump(xlswriter_get_version()); // 输出:string(5) "1.3.7"
获取当前固件的版本号。 请求方式: "|1|2|\r" 返回值: "|1|2|1.0|\r" 1.0表示当前固件是1.0版本 Arduino样例: softSerial.print("|1|2|\r");
; GetWindowsVersion ; ; 基于 Yazno 的函数,http://yazno.tripod.com/powerpimpit/ ; Joost Verburg 更新 ; ; 返回到堆栈顶 ; ; Windows 版本 (95、98、ME、NT x.x、2000、XP、2003) ; 或 ; '' (未知 Windows 版本) ; ;