【问题标题】:xpath attribute of root node根节点的xpath属性
【发布时间】:2012-02-20 01:10:25
【问题描述】:

我想获取根元素中的 ID、LASTEDITED、EXPIRESS 属性。我正在使用 xpath、ruby 和 nokogiri。但它不起作用,有什么想法吗?

xPath 查询:

  doc.xpath('/educationProvider/@id').each do |id_node| 
    puts node.content
  end

  doc.xpath('/educationProvider/@lastEdited').each do |lastedited_node|
    puts lastedited_node.content
  end

  doc.xpath('/educationProvider/@expires').each do |expires_node|
    puts expires_node.content
  end

这就是我的 XML 的样子:

<?xml version="1.0" encoding="UTF-8"?>
<p:educationProvider xmlns:p="http://skolverket.se/education/provider/1.0" xmlns="http://skolverket.se/education/commontypes/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expires="2015-01-31" id="provider.uh.msb" lastEdited="2012-11-01T12:51:37" xsi:schemaLocation="http://skolverket.se/education/provider/1.0 educationProvider.xsd">
        <p:vCard>
            <VERSION/> 
            <FN/> 
            <N/> 
            <ADR>
                <LOCALITY>KARLSTAD</LOCALITY> 
                <PCODE>651 81</PCODE> 
            </ADR>
            <TEL>
                <NUMBER>0771-240240</NUMBER> 
            </TEL>
            <EMAIL>
                <USERID>utbildning@msbmyndigheten.se</USERID> 
            </EMAIL>
            <ORG>
                <ORGNAME>Myndigheten för samhällsskydd och beredskap</ORGNAME> 
            </ORG>
            <URL>http://www.msbmyndigheten.se</URL>
        </p:vCard>
    </p:educationProvider>

这是我的红宝石脚本:

require 'rubygems'
require 'nokogiri'
require 'open-uri'

# parse the HTML document with all the links to the XML files.
doc = Nokogiri::HTML(open('http://testnavet.skolverket.se/SusaNavExport/EmilExporter?GetEvent&EMILVersion=1.1&NotExpired&EIAcademicType=UoH&SelectEP'))
# URLS - array
@urls = Array.new 
#Get all XML-urls and save them in urls-array
doc.xpath('//a/@href').each do |links|
  @urls << links.content
end

@id = Array.new
@lastedited = Array.new
@expires = Array.new

# loop all the url of the XML files
@urls.each do |url|
  doc = Nokogiri::HTML(open(url))
  # grab the content I want
  doc.xpath('/educationProvider/@id').each do |id_node| 
    id_node.content
  end

  doc.xpath('/educationProvider/@lastEdited').each do |lastedited_node|
    @lastedited << lastedited_node.content
  end

  doc.xpath('/educationProvider/@expires').each do |expires_node|
    @expires << expires_node.content
  end
end

#print it out
(0..@id.length - 1).each do |index|
  puts "ID: #{@id[index]}"
  puts "Lastedited: #{@lastedited[index]}"
  puts "Expiress: #{@expires[index]}"
end

【问题讨论】:

标签: xml xpath nokogiri


【解决方案1】:

我想在根目录中获取 ID、LASTEDITED、EXPIRESS 属性 元素。

只需使用

/*/@id

这将选择 XML 文档顶部元素的 id 属性。

/*/@lastEdited

这将选择 XML 文档顶部元素的 lastEdited 属性。

/*/@expires

这将选择 XML 文档顶部元素的 expires 属性。

或者,可以使用单个 XPath 表达式选择所有这三个属性

/*/@*[contains('|id|lastEdited|expires|', 
               concat('|', name(), '|')
               )
     ]

基于 XSLT 的验证:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/">
  <xsl:for-each select=
  "/*/@*[contains('|id|lastEdited|expires|',
                  concat('|', name(), '|')
                  )
         ]">
   <xsl:value-of select=
   "concat('&#xA;',
           name(),
           ' = ',
           .
          )"/>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

当此 XSLT 转换应用于提供的 XML 文档时

<p:educationProvider xmlns:p="http://skolverket.se/education/provider/1.0" xmlns="http://skolverket.se/education/commontypes/1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expires="2015-01-31" id="provider.uh.msb" lastEdited="2012-11-01T12:51:37" xsi:schemaLocation="http://skolverket.se/education/provider/1.0 educationProvider.xsd">
    <p:vCard>
        <VERSION/>
        <FN/>
        <N/>
        <ADR>
            <LOCALITY>KARLSTAD</LOCALITY>
            <PCODE>651 81</PCODE>
        </ADR>
        <TEL>
            <NUMBER>0771-240240</NUMBER>
        </TEL>
        <EMAIL>
            <USERID>utbildning@msbmyndigheten.se</USERID>
        </EMAIL>
        <ORG>
            <ORGNAME>Myndigheten för samhällsskydd och beredskap</ORGNAME>
        </ORG>
        <URL>http://www.msbmyndigheten.se</URL>
    </p:vCard>
</p:educationProvider>

计算 Xpath 表达式,并为每个选定的属性输出它们的名称和值

expires = 2015-01-31
id = provider.uh.msb
lastEdited = 2012-11-01T12:51:37

【讨论】:

  • 很好的答案,指定最后一个表达式。但我已经尝试过了,它不会打印出来..有些可疑..
  • @SHUMAcupcake: 呃……我更正了 XPath 表达式——现在试试。
  • 很抱歉,您在哪里更改了表达式,并在某处放置了额外的文件
  • @SHUMAcupcake:ipdated 表达式是最后一个表达式,它选择所有想要的属性。其中有必要将. 更改为name()。至于“更新的 ruby​​ 脚本”,不,我不能提供,比如我不是 Ruby 程序员。这个答案是纯 XPath 答案。当 Ruby 程序评估这个 XPath 表达式时,它将具有选定节点(对象)的列表(序列/数组)。然后取决于您的要求如何处理这些。
  • @SHUMAcupcake:这不是“脚本”,而是 XSLT 转换。它使用 XSLT 处理器运行(我每天使用十几种不同的 XSLT 处理器)。几乎所有 XSLT 处理器都具有命令行实用程序(例如用于 MSXML 的 msxsl.exe、用于 .NET XslCompiledTransform 的 nxslt.exe 等......)。转换也可以更方便地使用 IDE 进行开发和执行/调试,例如 XSeleretor(我正在使用)、oXygen 或 Visual Studio。
【解决方案2】:

如果你只是想访问文档中的根节点,你可以这样做:

root = doc.root
root_id = root['id']
last_edited = root['lastEdited']

如果您需要使用 XPath 找到它,您需要使用正确的命名空间。你的根节点有一个命名空间“p”,所以你必须这样做:

doc.xpath('/p:educationProvider/@id').first.value

注意您的节点名称前面的p:

【讨论】:

  • 我删除了 p: 因为我得到一个语法错误:未定义的命名空间前缀。你试过我的脚本吗?它对你有用吗,如果可以,请为我提供它。这个脚本是一个更大的脚本的一部分。我会很高兴,因为这让我很生气。
  • 我需要循环它,因为我正在抓取 4000 个具有相同 XML 结构的其他 XML 文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-20
相关资源
最近更新 更多