为什么XmlParser将我的字符十六进制代码字符串转换为unicode?

为什么XmlParser将我的字符十六进制代码字符串转换为unicode?,xml,grails,groovy,xml-parsing,xml-entities,Xml,Grails,Groovy,Xml Parsing,Xml Entities,在我的Grails应用程序中,我使用Groovy解析XML文件。我的XML文件中的一个属性的值是一个字符串,它等于一个字符的十六进制代码。我想在我的数据库中保存该字符串: Ñ 不幸的是,该方法返回字符,实际存储在数据库中的是c391。当该字段被读出时,我还得到了不需要的字符 如何将十六进制代码作为字符串存储在数据库中,并确保它也作为十六进制代码读取回来 更新#1: 这对我来说是个问题的原因是,一旦我将XML文件读入数据库,我必须能够完全按照原样重建它。另外一个问题是,所讨论的字段并不总是

在我的Grails应用程序中,我使用Groovy解析XML文件。我的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转换会导致一些十六进制代码值,例如
    ÿ更改为类似于ÿ的内容,而其他类似于
    和#x99保持不变

  • 我不确定这是否会成为一个问题,但当我重新创建文件时,我希望它采用
    ANSI
    编码,因为这是用于原始文件的编码

  • 好的,给定xml:

    def xml = '''<root>
        <node woo="&#xD1;"/>
        <another attr="This is an N-Tilde - &#xD1;"/>
    </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和我输入的一样,撒克逊人解析程序被这个字符阻塞了。这就是我发现这个问题的原因。