关于xml编码问题在VB,PHP,JAVA下的解决方案

xml|编码|解决|问题

    最近碰到一个项目,需要将申报文件存成XML的格式,编码问题着实让我头疼了一会。现在全部统一成UTF-8编码。具体在各种语言下的操作
  这里,我用DOM进行XML解析,应为它简单。

  1 客户首先使用VB进行编辑表单,生成一个apply.xml文件。

  在VB中,使用MSXML 4.0。如果不设定编码方式,保存的时候,文件默认就是UTF-8编码

    Set dom = CreateDOM
    Set node = dom.createProcessingInstruction("xml", "version='1.0'")
    dom.appendChild node
    Set node = Nothing

  2 接下来,客户将这个XML通过Web上传到服务器

  在PHP中,XMLDOM只支持UTF-8作为默认编码。所以生成的XML文件,上传以后可以直接解析这个文件,获得一些信息

  if (!$dom = domxml_open_mem($content)) {
      $t->assign('msg', "文件解析错误!");
      $t->render('noavailable.html', PAGE_TITLE, 'wrap.html');
      exit;
    }

  接下来,要将这个文件存到数据库里面,因为数据库使用MS Sql Server,它不支持UTF-8的数据结构,所以将整个文件以二进制的方式存到数据库里面,这里让我搞了半天的就是二进制文件的存放方式,如果是mysql,那不需要做任何转换就可以直接存了,但是mssql不行,原因是:

This is because the MSSQL parser makes a clear distinction between binary an character constants. You can therefore not easilly insert binary data with "column = '$data'" syntax like in MySQL and others.

The MSSQL documentation states that binary constants should be represented by their unquoted hexadecimal byte-string. That is.. to set the binary column "col" to contain the bytes 0x12, 0x65 and 0x35 you shold do "col = 0x126535" in you query.

  具体操作如下:

    //读取上传的文件
    $original = $_FILES['content']['name'];
      if (!empty($original)) {
          if ($_FILES['content']['type'] == "text/xml") {
           $filename = $_FILES['content']['tmp_name'];
            $handle = fopen($filename, "rb");
            $originalcontent = fread($handle, filesize($filename));
           
            fclose($handle);
           }
      } //end  if(!empty($original)) 

$originalcontent = unpack("H*hex", $originalcontent); //这步是关键

 $db->query("insert into ".TBL_SB_ONLINE_USER." (sb_id, user_id, username, sbmc, content, created_date) values ("
        .$newid.", "
        .$u.", "
        .$db->quote(stripslashes($name)).", "
        .$db->quote(stripslashes($sbmc)).", 0x"
        .$originalcontent['hex'].", "      //注意这里,前面有0x
        ."'$now')");

  3 上传之后,用户也可以在网上对这个文件进行在线编辑,这时需要将这个文件从数据库读出,然后还原成UTF-8编码,再进行解析。虽然我们上面使用了unpack,但读出的时候不需要还原。

 $sb = $db->getRow('select sbmc, content from '.TBL_SB_ONLINE_USER." where sb_id = $sb_id");
 $originalcontent =$sb[content];

 if (!$dom = domxml_open_mem($originalcontent)) {
      $t->assign('msg', "文件解析错误!");
      $t->render('noavailable.html', PAGE_TITLE, 'wrap.html',true);
      exit;
    }
   
    $context = xpath_new_context($dom);
   
    $xpath = $context->xpath_eval("//material/xm");
    $t->assign('xm',iconv("UTF-8","GBK",$xpath->nodeset[0]->get_content()));

  读出的时候,mssql除了用于 SQL Server 的 Microsoft OLE DB 提供程序和 SQL Server ODBC 驱动程序自动将 @@TEXTSIZE 设置为最大值 2 GB。其他的都是4096 (4 KB),所以用PHP访问时候,务必将下面打开mssql.textlimit = 2147483647
mssql.textsize = 2147483647

  4 后台用VB,要解析该函数需要添加以下代码,用来将byte()转换成utf-8编码

Public Declare Function MultiByteToWideChar Lib "kernel32" (ByVal CodePage As Long, ByVal dwFlags As Long, ByVal lpMultiByteStr As Long, _
ByVal cchMultiByte As Long, ByVal lpWideCharStr As Long, ByVal cchWideChar As Long) As Long

Public Const CP_UTF8 = 65001

Public Function UTF8_Decode(bUTF8() As Byte) As String
Dim lRet As Long
Dim lLen As Long
Dim lBufferSize As Long
Dim sBuffer As String
Dim bBuffer() As Byte
lLen = UBound(bUTF8) + 1
If lLen = 0 Then Exit Function
lBufferSize = lLen * 2
sBuffer = String$(lBufferSize, Chr(0))
lRet = MultiByteToWideChar(CP_UTF8, 0, VarPtr(bUTF8(0)), lLen, StrPtr(sBuffer), lBufferSize)
If lRet <> 0 Then
sBuffer = Left(sBuffer, lRet)
End If
UTF8_Decode = sBuffer
End Function

  具体读数据库的操作是

   Dim varcontent() As Byte
    varfilesize = mrc.Fields("content").ActualSize
    varcontent = mrc.Fields("content").GetChunk(varfilesize)
    content = UTF8_Decode(varcontent)

    xmlDoc.async = False
    xmlDoc.resolveExternals = False
    xmlDoc.loadXML (content)
    If (xmlDoc.parseError.errorCode <> 0) Then
      Dim myErr
      Set myErr = xmlDoc.parseError
      MsgBox ("发生错误 " & myErr.reason)
    Else
      xmlDoc.setProperty "SelectionLanguage", "XPath"

  5 后台,在Java里面就更好操作了,将读出的数据变成byte[],然后转换成UTF-8的字符串。

  最后要说的是,PHP的确是一个非常强大的脚本语言,如果开发PHP过程中遇到难以解决,google都不容易搜到的问题,大家直接上php.net的在线文档,文档里面通常有很多好心人将自己的使用心得写在上面,非常有帮助。

时间: 2024-11-01 06:50:21

关于xml编码问题在VB,PHP,JAVA下的解决方案的相关文章

XML指南——XML编码

xml|编码    XML文档可以包含外文字符比如挪威语或者法语(中文当然也可以!这一部分还是不能照原文翻译,下面有些内容是我自己写的) 为了让你的解析器能够明白这些字符,你必须在XML文档中统一的字符编码标准. Windows 95/98 记事本 Windows 95/98 记事本不能以Unicode的编码格式保存文件. 可以使用记事本来编辑和保存包含了外文字符的XML文档 (比如:挪威语或者法语或者中文) <?xml version="1.0"?> <note&g

XML 编码

xml|编码   XML 文档中可以包含外语字母,如挪威语 ??? 或法语 êèé.要让你的XML分解器理解这些字母,就应该把XML文档存储成Unicode(统一的字符编码标准).          b>Windows 95/98 记事本       Windows 95/98 记事本不能将文件保存成Unicode 格式.你可以用Notepad 编辑和保存包含外语字母(如挪威语和法语的??? 和 êèé)的XML 文档,       < ?xml version="1.0"

XmlDocument XML编码转换

最近做一个RSS在线聚合器,大部分RSS 2.0编码的XML编码.NET编译器都可以 正确读取,可是一些比如GBK编码,我们的.NET就读取不了,如果把那个XML的编 码手动改变成"gb2312"或者其它编码,也是读取不了.不过编码改 变不改变,IE都是可以正确查看的.下面怎么办,确实难住我了.改变编码怎么 样?我的RSS在线聚合器要读取的RSS 2.0文件不是下载到本地的文件,而是在线 阅读.那好,得到连接后,使用流可以很好的得到正确编码的XML流.下面见代码 啦: 1 privat

Java中的字符集编码入门(六) Java中的增补字符

Java号称对Unicode提供天然的支持,这话在很久很久以前就已经是假的了(不过曾经是真的),实际上,到JDK5.0为止,Java才算刚刚跟上Unicode的脚步,开始提供对增补字符的支持. 现在的Unicode码空间为U+0000到U+10FFFF,一共1114112个码位,其中只有1,112,064 个码位是合法的(我来替你做算术,有2048个码位不合法),但并不是说现在的Unicode就有这么多个字符了,实际上其中很多码位还是空闲的,到Unicode 4.0 规范为止,只有96,382个

编程语言 c++应用方向-C++,VB,Java等编程语言的区别及应用领域

问题描述 C++,VB,Java等编程语言的区别及应用领域 作为一个新手,我想知道Visual C++和Visual Basic,Java的区别,我学的是C++,但是不知道用C++可以做些什么,希望有高手指明一下方向. 解决方案 我个人认为,C更接近底层设备,也就是说一般c用来和硬件打交道,java更适合一些应用程序的编写,学习C++其实就是从C到java的一个过渡!面向过程编程到面向对象编程的过度! 解决方案二: c++语言是面向对象的编程语言,它认为世间一切都是由对象(object)组装起来

接口-android中的xml里实现onClick=“clickButton” 在java中……

问题描述 android中的xml里实现onClick="clickButton" 在java中-- 1.对Android中的xml实现onClick有点疑问,实现的原理是怎样的? 2.java中实现是这样的: view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { } }); 3.xml结合java的实现样式比较好看,可是他没有实现OnClickListener的接

编程-民工甲在Swing是一把刀里面写用xml制作菜单,我没看懂,是用xml写出菜单然后用Java调用?

问题描述 民工甲在Swing是一把刀里面写用xml制作菜单,我没看懂,是用xml写出菜单然后用Java调用? XML配置 每个应用程序都千奇百怪,功能各异.如何用一个同样的界面来组织呢?的确,这个界面并非适合所有人.不过这里的所有菜单.按钮.流程图.图标等,其动作都是可以用一个"动作码"类定义的,所有的动作都会回调一个统一的函数.而我们只要在这个函数处插入监听,就可以拦截具体动作码,执行我们想做的任何事情,例如格式化C盘.往aobama@whitehouse.com邮箱发个垃圾邮件啥的

stylesheet-bootstrap中的导航中java为何在360浏览器java下拉菜单点了没反应

问题描述 bootstrap中的导航中java为何在360浏览器java下拉菜单点了没反应 <!DOCTYPE html> Bootstrap 实例 - 带有下拉菜单的标签 带有下拉菜单的标签 Home SVN iOS VB.Net Java Swing jMeter EJB 分离的链接 PHP 以下是显示的图片 解决方案 电脑感染了360等非法流氓软件 解决方案二: 有可能是浏览器禁用了js--换个浏览器--比如谷歌火狐--

在Java下利用log4j记录日志的方法_java

1.前言 log4j是一个用Java编写的可靠,快速和灵活的日志框架(API),它在Apache软件许可下发布. Log4j已经被移植到了C,C++,C#,Perl,Python和Ruby等语言中. Log4j是高度可配置的,并可通过在运行时的外部文件配置.它根据记录的优先级别,并提供机制,以指示记录信息到许多的目的地,例如:数据库,文件,控制台,UNIX系统日志等. Log4j中有三个主要组成部分:     loggers: 负责捕获记录信息.     appenders : 负责发布日志信息