使用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
相关产品推荐
相关产品推荐

