为什么XmlParser将我的字符十六进制代码字符串转换为unicode?
在我的Grails应用程序中,我使用Groovy解析XML文件。我的XML文件中的一个属性的值是一个字符串,它等于一个字符的十六进制代码。我想在我的数据库中保存该字符串:为什么XmlParser将我的字符十六进制代码字符串转换为unicode?,xml,grails,groovy,xml-parsing,xml-entities,Xml,Grails,Groovy,Xml Parsing,Xml Entities,在我的Grails应用程序中,我使用Groovy解析XML文件。我的XML文件中的一个属性的值是一个字符串,它等于一个字符的十六进制代码。我想在我的数据库中保存该字符串: Ñ 不幸的是,该方法返回字符,实际存储在数据库中的是c391。当该字段被读出时,我还得到了不需要的字符 如何将十六进制代码作为字符串存储在数据库中,并确保它也作为十六进制代码读取回来 更新#1: 这对我来说是个问题的原因是,一旦我将XML文件读入数据库,我必须能够完全按照原样重建它。另外一个问题是,所讨论的字段并不总是
Ñ代码>
不幸的是,该方法返回字符,实际存储在数据库中的是c391
。当该字段被读出时,我还得到了不需要的字符
如何将十六进制代码作为字符串存储在数据库中,并确保它也作为十六进制代码读取回来
更新#1:
这对我来说是个问题的原因是,一旦我将XML文件读入数据库,我必须能够完全按照原样重建它。另外一个问题是,所讨论的字段并不总是字符十六进制代码。它可能只是一些任意的字符串
更新#2:
我想这与字符在数据库中的存储方式无关,只要我能以扩展的十六进制代码格式将其写出来就行。我正在使用Groovy从数据库中重建XML文件,我不清楚为什么默认情况下不会发生这种情况
更新#3:
我在自定义MySQL方言中重写了getTableTypeString
,这似乎对一些事情有所帮助。至少现在我传递给MySQL的值是存储在数据库中的值
class CustomMySQL5InnoDBDialect extends MySQL5InnoDBDialect {
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8"
}
}
我还创建了自己版本的。我的版本与groovy.util.XmlParser
几乎完全相同,只是在startElement
方法中我更改了:
String value = list.getValue(i)
为此:
def value = list.fAttributes.fAttributes[i].nonNormalizedValue
if(value ==~ /&#x([0-9A-F]+?);/) {
value = list.fAttributes.fAttributes[i].nonNormalizedValue
}
这允许在数据库中存储十六进制代码元素的确切文本
class CustomMySQL5InnoDBDialect extends MySQL5InnoDBDialect {
@Override
public String getTableTypeString() {
return " ENGINE=InnoDB DEFAULT CHARSET=utf8"
}
}
现在有两个新问题,可能是三个
使用存储在数据库中的精确值重新创建文件。到目前为止,我一直在使用MarkupBuilder
,但这是在对符号和进行额外编码,导致值Ñ代码>将作为写入&#xD1
我可能可以通过放弃MarkupBuilder
并手动构建XML字符串来解决这个问题,但我宁愿不这样做
使用Saxon HE 9.4处理器在XML文件上运行XSLT转换会导致一些十六进制代码值,例如ÿ将code>更改为类似于ÿ的内容,而其他类似于和#x99代码>保持不变
我不确定这是否会成为一个问题,但当我重新创建文件时,我希望它采用ANSI
编码,因为这是用于原始文件的编码
好的,给定xml:
def xml = '''<root>
<node woo="Ñ"/>
<another attr="This is an N-Tilde - Ñ"/>
</root>'''
然后将其打印出来,给我们提供“ñ”
(字符值为209
)
但这正是我所期望的。。。asÑ
与和#209相同代码>哪个是
啊,问题是“我如何读取属性,并保持它们不变而不进行任何实体解析”
我不相信你能(我所看到的只是网络搜索的否定答案)。。。你能做的是:
// Mask entities
xml = xml.replaceAll( /&#x([0-9A-F]+?);/, '!!#x$1;' )
def parser = new XmlParser().parseText( xml )
println parser.node[0].@attr.replaceAll( /!!#x([0-9A-F]+?);/, '&#x$1;' )
println parser.another[0].@attr.replaceAll( /!!#x([0-9A-F]+?);/, '&#x$1;' )
但据我所知,没有一种方法可以调整实体分辨率:-(但愿我错了)
我的XML文件中的一个属性的值是一个字符串,它等于一个字符的十六进制代码
不,它不是。原始XML中属性值的表示形式是十六进制字符引用,但属性值是字符ñ。有一些方法可以配置一些XML解析器,以避免在解析期间扩展命名实体引用,但它们必须根据XML规范扩展数字字符引用
您还没有说明为什么存储真实字符值是一个问题。如果这与将值呈现给浏览器有关,那么可以使用.encodeAsHTML()来处理
在输出时。如果您需要将值保存到另一个XML文件中,则使用XML API来执行此操作,它将为您处理编码问题,将字符替换为实体或字符引用,以保持结果格式良好(对于ñ,它无论如何都不需要转义,除非您正在用不寻常的字符集编写XML)
在Groovy的MarkupBuilder的特定情况下,您可以暂时脱离XML模式,并使用直接将手工构造的标记写入输出流,这样您就可以在生成器通常不会打扰的地方输出字符引用。我更新了我的问题,以说明为什么这对我来说是个问题。@ubiquibacon如果您的同事de关心、和#xD1;
、和#xD1;
等之间的区别。然后您就不能使用XML工具来解析数据。XML解析器根本不会告诉您原始源代码中使用了哪种词汇表示。我在问题中添加了一些新信息。看起来我无法使用任何基于SAX的解析器来读取数据字符十六进制代码为字符串,但您可能知道一种制作Groovy(或等效代码)的方法用扩展的十六进制代码格式写出有问题的字符。@ubiquibacon XML API将转义任何需要转义的字符,而不是不需要转义的字符。如果您使用UTF-8编写XML,则可以不转义地编写
。如果您将其编写为US-ASCII,则将其转义为&xD1;
或&209;
或者其他一些等效的字符引用。我再说一遍-如果您关心这一级别的细节,那么您不是在处理XML,也不能使用XML工具,相反,您必须自己将标记构造为字符串。我用UTF-8编写XML,并将其写入文件中。此外,我还需要能够生成XML和我输入的一样,撒克逊人解析程序被这个字符阻塞了。这就是我发现这个问题的原因。