【问题标题】:Can Nokogiri search for "?xml-stylesheet" tags?Nokogiri 可以搜索“?xml-stylesheet”标签吗?
【发布时间】:2012-10-28 03:09:53
【问题描述】:

我需要解析一个 XML 样式表:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/templates/xslt/inspections/disclaimer_en.xsl"?>

我尝试使用 Nokogiri:

doc.search("?xml-stylesheet").first['href']

但我得到了错误:

`on_error': unexpected '?' after '' (Nokogiri::CSS::SyntaxError)

【问题讨论】:

    标签: ruby xml nokogiri


    【解决方案1】:

    Nokogiri 无法搜索属于 XML 处理指令的标签。您可以像这样访问它们:

    doc.children[0]
    

    【讨论】:

    • -1 这对我在 Nokogiri 1.5.5 上不起作用:p Nokogiri.XML('&lt;?xml version="1.0" encoding="UTF-8" ?&gt;&lt;Foo /&gt;').children[0] #=&gt; #&lt;Nokogiri::XML::Element:0x323df0 name="Foo"&gt;
    • 两年前确实有效,但可以从内部更改 Nokogiri。当然,在写这个答案的那一刻,我测试了我的代码。
    • 我真的相信你。我在内部纠结于如何处理曾经明确正确但不再有效的问题的旧答案。我目前的信念是,当存在替代的正确答案时,应该不赞成这样的答案。我不是要惩罚你(当然不是!),而是要表明答案(不再)有帮助。
    【解决方案2】:

    这不是 XML 元素;这是一个 XML "Processing Instruction"。这就是您无法通过查询找到它的原因。找到你想要的:

    # Find the first xml-stylesheet PI
    xss = doc.at_xpath('//processing-instruction("xml-stylesheet")')
    
    # Find every xml-stylesheet PI
    xsss = doc.xpath('//processing-instruction("xml-stylesheet")')
    

    实际操作:

    require 'nokogiri'
    xml = <<ENDXML
      <?xml version="1.0" encoding="UTF-8"?>
      <?xml-stylesheet type="text/xsl" href="/templates/disclaimer_en.xsl"?>
      <root>Hi Mom!</root>
    ENDXML
    doc = Nokogiri.XML(xml)
    xss = doc.at_xpath('//processing-instruction("xml-stylesheet")')
    puts xss.name     #=> xml-stylesheet
    puts xss.content  #=> type="text/xsl" href="/templates/disclaimer_en.xsl"
    

    由于处理指令不是元素,它没有属性;例如,您不能要求xss['type']xss['href'];如果您愿意,您需要将内容解析为元素。一种方法是:

    class Nokogiri::XML::ProcessingInstruction
      def to_element
        document.parse("<#{name} #{content}/>")
      end
    end
    
    p xss.to_element['href'] #=> "/templates/disclaimer_en.xsl"
    

    请注意,在 Nokogiri 或 libxml2 中存在 a bug,如果在 @987654331 之前至少有一个字符(可以是空格),这将导致 XML Declaration 在文档中显示为 Processing Instruction @。这就是为什么在上面我们专门搜索名称为xml-stylesheet的处理指令。

    编辑:XPath 表达式processing-instruction()[name()="foo"] 等价于表达式processing-instruction("foo")。如XPath 1.0 spec中所述:

    processing-instruction() 测试可能有一个字面量参数;在这种情况下,对于任何名称等于 Literal 值的处理指令都是如此。

    我已经编辑了上面的答案以使用较短的格式。

    【讨论】:

    • 请注意,如果您知道每个 PI 都位于文档的根目录 - 而不是文档深处某个元素的子元素 - 您可以使用 @987654336 使您的搜索更加高效@.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    相关资源
    最近更新 更多