You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Nokogiri解析XML文件生成LaTeX的\index字段求助

解决方案:用Nokogiri解析带格式XML生成LaTeX \index{}命令

核心问题是需要保留XML字段中的格式标记(如斜体、粗体),而非仅提取纯文本。以下是完整的Ruby+Nokogiri实现代码及分步解释:

1. 核心函数:解析带格式的字段内容

遍历<field>下的所有子节点,将XML格式标记转换为对应LaTeX命令:

def parse_formatted_text(field_node)
  output = []
  current_styles = []

  field_node.children.each do |node|
    if node.element?
      case node.name
      when 'text'
        # 处理样式开启/关闭标签
        if style = node['style']
          latex_cmd = case style
                      when 'i' then 'textit'
                      when 'b' then 'textbf'
                      end
          if latex_cmd
            current_styles << latex_cmd
            output << "\\#{latex_cmd}{"
          end
        else
          # 空<text/>标签用于关闭样式
          unless current_styles.empty?
            output << "}"
            current_styles.pop
          end
        end
      when 'hide'
        # <hide>内容直接保留(参与显示但不参与排序)
        output << node.text.strip
      end
    elsif node.text?
      # 普通文本节点直接加入
      output << node.text.strip
    end
  end

  # 容错处理:自动闭合未关闭的样式标签
  current_styles.size.times { output << "}" }

  output.join(' ')
end

2. 提取索引排序键

从主条目字段中提取用于LaTeX索引排序的关键字(示例中为Titanic,而非带前缀的SS Titanic):

def extract_sort_key(field_node)
  sort_text = []
  hide_found = false

  field_node.children.each do |node|
    if node.name == 'hide'
      hide_found = true
      next
    end
    # 跳过样式标签,只提取hide之后的纯文本
    sort_text << node.text.strip if hide_found && node.text?
  end

  sort_text.join.strip
end

3. 处理单个索引记录

将<record>中的字段拼接成完整的\index{}命令:

def process_record(record_node)
  fields = record_node.xpath('./field')
  locator_field = fields.find { |f| f['class'] == 'locator' }
  main_fields = fields.reject { |f| f['class'] == 'locator' }

  # 处理主条目
  main_field = main_fields[0]
  main_display = parse_formatted_text(main_field)
  sort_key = extract_sort_key(main_field)

  # 处理子条目
  sub_entries = main_fields[1..-1].map { |f| parse_formatted_text(f) }

  # 构建索引命令主体
  index_parts = []
  index_parts << (sort_key != main_display ? "#{sort_key}@#{main_display}" : main_display)
  index_parts += sub_entries

  # 添加页码格式(如|textbf)
  if locator_field
    style = locator_field.at_xpath('./text[@style]')&.[]('style')
    index_parts.last << '|textbf' if style == 'b'
  end

  # 提取定位数字(中间输出用,最终LaTeX源文件无需保留)
  locator_number = locator_field&.text&.strip

  "\\index{#{index_parts.join('!')}} #{locator_number}"
end

4. 测试示例

使用你提供的XML测试代码:

require 'nokogiri'

xml_content = <<~XML
<record time="2022-08-27T17:25:12" id="30">
    <field><text style="i"/><hide>SS </hide>Titanic<text/></field>
    <field>passengers</field>
    <field class="locator"><text style="b"/>5<text/></field>
</record>
XML

doc = Nokogiri::XML(xml_content)
record = doc.at_xpath('//record')
puts process_record(record)

运行后输出:

\index{Titanic@\textit{SS Titanic}!passengers|textbf} 5

关键说明

  • 样式扩展:可通过扩展latex_cmd的case分支,添加更多XML样式与LaTeX命令的映射。
  • 容错机制:自动闭合未关闭的样式标签,避免LaTeX编译错误。
  • 排序逻辑:通过<hide>标签区分显示文本和排序关键字,适配索引软件的常见输出规范。

内容的提问来源于stack exchange,提问作者Don H

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 10:54:51