Rails+Builder.生成不带实体的 XML 输出

发布于 2024-11-26 17:47:26 字数 1020 浏览 0 评论 0原文

如何使 Builder 不编码“śćż”和其他此类字符。 我想要的是“całość”按字面意思打印在 XML 文档中。 示例:

xml.instruct! :xml, :version => '1.0', :encoding => 'utf-8'
xml.Trader( :'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
            :'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema") do
  xml.Informacje do
    xml.RodzajPaczki 'całość'
    xml.Program 'mine'
    xml.WersjaProgramu '1.0'
  end
end

输出:

<?xml version="1.0" encoding="utf-8"?> 
<Trader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
 <Informacje>  
  <RodzajPaczki>ca&#322;o&#347;&#263;</RodzajPaczki> 
    <Program>mine</Program> 
    <WersjaProgramu>1.0</WersjaProgramu> 
  </Informacje>
</Trader> 

ca&#322;o&#347;&#263; 应为 całość。 我看到了像 xml.RodzajPaczki {|t| 这样的伪解决方案t << 'całość' } 但它无法正常工作。它将“całość”突出到文档的左侧。

How to make Builder to not encode 'śćż' and other such characters.
What I want is 'całość' to be literally printed in XML document.
Example:

xml.instruct! :xml, :version => '1.0', :encoding => 'utf-8'
xml.Trader( :'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
            :'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema") do
  xml.Informacje do
    xml.RodzajPaczki 'całość'
    xml.Program 'mine'
    xml.WersjaProgramu '1.0'
  end
end

Output:

<?xml version="1.0" encoding="utf-8"?> 
<Trader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
 <Informacje>  
  <RodzajPaczki>całość</RodzajPaczki> 
    <Program>mine</Program> 
    <WersjaProgramu>1.0</WersjaProgramu> 
  </Informacje>
</Trader> 

całość should be całość.
I saw pseudo solution like xml.RodzajPaczki {|t| t << 'całość' } but it does not work correctly. It outdent 'całość' to left side of a document.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沉睡月亮 2024-12-03 17:47:26

这就是正在发生的事情。正如我们所知,默认情况下 Builder 会转义非 ASCII 字符,例如 całość 中的字符。您还提到了一种可能的修复方法,那就是:

xml.RodzajPaczki {|t| t << 'całość' }

不幸的是,当您将一个块传递给 RodzajPaczki 元素时,Builder 假定会有一些内部 xml,因此它会添加一个新行并应用缩进。当然,在我们的例子中,只有内部文本,没有 xml,因此我们会得到一些难看的输出,例如:

<RodzajPaczki>
całość      </RodzajPaczki>

有一个简单的方法和一个更难的方法来解决这个问题。首先是简单的方法。

将缩进配置为零

然后您可以使用上面的修复xml.RodzajPaczki {|t| t << 'całość' } 一切都会按预期工作,但输出不会被漂亮地打印出来,它实际上会全部在一行上:

<?xml version="1.0" encoding="UTF-8"?><Trader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Informacje><RodzajPaczki>całość</RodzajPaczki><Program>mine</Program><WersjaProgramu>1.0</WersjaProgramu></Informacje></Trader>

如果您希望它具有良好的格式,您可以通过外部漂亮的打印机运行它。

如果您只是必须有漂亮的打印输出并且不想转义,我们需要稍微修补 Builder。这是解决此问题的更困难的方法。

修补构建器

我们需要修补 XmlMarkup 对象的初始化程序以添加额外的选项 :escape。同时,我们修补 XmlBase 对象以将此新选项作为参数。我们将此新选项默认为 true,以维持默认行为。然后,我们修补 XmlBase 上的 text! 方法,以使用我们的新选项来决定是否应该转义文本。它看起来是这样的:

module Builder
  class XmlBase
    def initialize(indent=0, initial=0, encoding='utf-8', escape=true)
      @indent = indent
      @level  = initial
      @encoding = encoding.downcase
      @escape = escape
    end

    def text!(text)
      if @escape
        _text(_escape(text))
      else
        _text(text)
      end
    end
  end

  class XmlMarkup
    def initialize(options={})
      indent = options[:indent] || 0
      margin = options[:margin] || 0
      encoding = options[:encoding] || 'utf-8'
      escape = options[:escape]
      if escape == nil
        escape = true
      end
      super(indent, margin, encoding, escape)
      @target = options[:target] || ""
    end
  end
end

我们现在可以通过以下方式使用新修补的构建器(请注意,当我们构造 XmlMarkup 对象时,我们会传入新的 : escape 选项(值为 false):

xml = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>3, :encoding => 'utf-8', :escape => false)
xml.instruct! :xml, :version => '1.0', :encoding => 'UTF-8'
xml.Trader(:'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", :'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema") do 
  xml.Informacje do
    xml.RodzajPaczki('całość')
    xml.Program('mine')
    xml.WersjaProgramu('1.0')
  end
end

输出如下:

<?xml version="1.0" encoding="UTF-8"?>
<Trader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <Informacje>
      <RodzajPaczki>całość</RodzajPaczki>
      <Program>mine</Program>
      <WersjaProgramu>1.0</WersjaProgramu>
   </Informacje>
</Trader>

根据需要,文本不会转义。请注意,该补丁会将这种非转义行为应用于所有文本,因此,如果您只想对某些文本进行非转义,而其他文本仍进行转义,则需要在更大程度上修补 Builder。

Here is what is happening. As we know by default Builder will escape non ASCII characters like the ones in całość. You've also mentioned one possible way to kinda fix it and that is:

xml.RodzajPaczki {|t| t << 'całość' }

Unfortunately when you pass a block to the RodzajPaczki element, Builder assumes that there will be some inner xml, so it adds a new line and applies the indent. Of course in our case there is only inner text and no xml so we get some unsightly output like:

<RodzajPaczki>
całość      </RodzajPaczki>

There is an easy way and a harder way to fix this. First the easy way.

Configure Indent To Be Zero

Then you can use the fix from above xml.RodzajPaczki {|t| t << 'całość' } everything will work as expected, but the output will not be pretty printed, it will infact be all on one line:

<?xml version="1.0" encoding="UTF-8"?><Trader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><Informacje><RodzajPaczki>całość</RodzajPaczki><Program>mine</Program><WersjaProgramu>1.0</WersjaProgramu></Informacje></Trader>

You can run this through an external pretty printer if you want it nicely formatted.

If you simply must have pretty printed output and want no escaping, we need to patch Builder slightly. This is the harder way to fix this issue.

Patching Builder

We need to patch the initializer of our XmlMarkup object to add an extra option :escape. At the same time we patch the XmlBase object to take this new option as a parameter. We default this new option to true, to maintain the default behaviour. We then patch the text! method on XmlBase to use our new option to decide if we should escape text of not. Here is what it looks like:

module Builder
  class XmlBase
    def initialize(indent=0, initial=0, encoding='utf-8', escape=true)
      @indent = indent
      @level  = initial
      @encoding = encoding.downcase
      @escape = escape
    end

    def text!(text)
      if @escape
        _text(_escape(text))
      else
        _text(text)
      end
    end
  end

  class XmlMarkup
    def initialize(options={})
      indent = options[:indent] || 0
      margin = options[:margin] || 0
      encoding = options[:encoding] || 'utf-8'
      escape = options[:escape]
      if escape == nil
        escape = true
      end
      super(indent, margin, encoding, escape)
      @target = options[:target] || ""
    end
  end
end

We can now use our newly patched builder in the following way (notice that when we construct the XmlMarkup object we pass in our new :escape options with a value of false):

xml = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>3, :encoding => 'utf-8', :escape => false)
xml.instruct! :xml, :version => '1.0', :encoding => 'UTF-8'
xml.Trader(:'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance", :'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema") do 
  xml.Informacje do
    xml.RodzajPaczki('całość')
    xml.Program('mine')
    xml.WersjaProgramu('1.0')
  end
end

The output is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<Trader xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
   <Informacje>
      <RodzajPaczki>całość</RodzajPaczki>
      <Program>mine</Program>
      <WersjaProgramu>1.0</WersjaProgramu>
   </Informacje>
</Trader>

As desired the text is not escaped. Note that the patch will apply this non-escaping behaviour to all text, so if you only want some of the text to be non-escaped while other text is still escaped you'll need to patch Builder to a much greater extent.

鸢与 2024-12-03 17:47:26

我无法使用我的设置复制此内容。您使用什么版本的 ruby​​/rails/builder?

I cannot replicate this using my setup. What version of ruby/ rails/ builder are you using?

我一直都在从未离去 2024-12-03 17:47:26

我可以毫无问题地输出“całość”(Ruby 1.9.2,Builder 3.0.0)。
手册页 http://builder.rubyforge.org/ 建议设置 $KCODE'UTF8' (参见页面的最后),但我认为这是针对 Ruby 1.8 的。
我的文件中的内容类似于:

#!/usr/bin/ruby -wE UTF-8:UTF-8
# encoding: UTF-8

require 'builder'
...

xml = Builder::XmlMarkup.new( :target => target, :indent => 2 )
xml.instruct! :xml, :version => '1.0', :encoding => 'UTF-8'
...

I can output "całość" without problems (Ruby 1.9.2, Builder 3.0.0).
The manual page http://builder.rubyforge.org/ suggests to set $KCODE to 'UTF8' (see the very end of the page), but i think this is for Ruby 1.8.
What i have in my file, is something like:

#!/usr/bin/ruby -wE UTF-8:UTF-8
# encoding: UTF-8

require 'builder'
...

xml = Builder::XmlMarkup.new( :target => target, :indent => 2 )
xml.instruct! :xml, :version => '1.0', :encoding => 'UTF-8'
...
安稳善良 2024-12-03 17:47:26

中的评论Rails 票证 #1446 表明这可能会在 Builder 3.0.0 中修复。不过我自己还没有尝试过。

A comment in Rails ticket #1446 indicates that this may be fixed in Builder 3.0.0. I haven't tried it yet myself however.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文