2015-09-17 3 views
1

У меня возникла проблема с получением REXML::XPath.first, чтобы отобразить правильный текст узла из дочернего контекста.Как получить текст узла из дочернего контекста с использованием ruby, xpath, rexml

См. Тестовый скрипт и xml ниже.

test.rb

require 'rexml/document' 
require 'rexml/xpath' 

file = File.new('test.xml') 
doc = REXML::Document.new(file) 

employers = REXML::XPath.match(doc, '//EmployerOrg') 
employers.each do |employer| 
    # this looks fine, position_history is being set for each employer 
    position_history = REXML::XPath.first(employer, 'PositionHistory') 

    # always returns the title from the first employer, in spite of the position_history context 
    p title = REXML::XPath.first(position_history, '//Title').text 
end 

Выход:

"Director of Web Applications Development" 
"Director of Web Applications Development" 
"Director of Web Applications Development" 

Пример XML:

<?xml version="1.0" encoding="UTF-8"?> 
<Resume xml:lang="en" xmlns="http://ns.hr-xml.org/2006-02-28" xmlns:sov="http://sovren.com/hr-xml/2006-02-28"> 
    <StructuredXMLResume> 
    <EmploymentHistory> 
     <EmployerOrg> 
     <EmployerOrgName>Technical Difference</EmployerOrgName> 
     <PositionHistory positionType="directHire" currentEmployer="true"> 
      <Title>Director of Web Applications Development</Title> 
      <OrgName> 
      <OrganizationName>Technical Difference</OrganizationName> 
      </OrgName> 
      <StartDate> 
      <AnyDate>2004-10-01</AnyDate> 
      </StartDate> 
      <EndDate> 
      <AnyDate>2015-09-15</AnyDate> 
      </EndDate> 
     </PositionHistory> 
     </EmployerOrg> 
     <EmployerOrg> 
     <EmployerOrgName>Convergence Inc. LLC</EmployerOrgName> 
     <PositionHistory positionType="directHire"> 
      <Title>Senior Web Developer/DBA</Title> 
      <OrgName> 
      <OrganizationName>Convergence Inc. LLC</OrganizationName> 
      </OrgName> 
      <StartDate> 
      <AnyDate>2003-03-01</AnyDate> 
      </StartDate> 
      <EndDate> 
      <AnyDate>2004-12-01</AnyDate> 
      </EndDate> 
      <UserArea> 
      <sov:PositionHistoryUserArea> 
       <sov:Id>POS-2</sov:Id> 
       <sov:CompanyNameProbability>23</sov:CompanyNameProbability> 
       <sov:PositionTitleProbability>30</sov:PositionTitleProbability> 
      </sov:PositionHistoryUserArea> 
      </UserArea> 
     </PositionHistory> 
     </EmployerOrg> 
     <EmployerOrg> 
     <EmployerOrgName>Avalon Digital Marketing Systems, Inc</EmployerOrgName> 
     <PositionHistory positionType="contract"> 
      <Title>Contractor - Web Development</Title> 
      <OrgName> 
      <OrganizationName>Avalon Digital Marketing Systems, Inc</OrganizationName> 
      </OrgName> 
      <StartDate> 
      <AnyDate>2002-05-01</AnyDate> 
      </StartDate> 
      <EndDate> 
      <AnyDate>2003-03-01</AnyDate> 
      </EndDate> 
     </PositionHistory> 
     <PositionHistory positionType="directHire"> 
      <Title>Web Developer/Junior DBA</Title> 
      <OrgName> 
      <OrganizationName>European Division</OrganizationName> 
      </OrgName> 
      <StartDate> 
      <AnyDate>2000-05-01</AnyDate> 
      </StartDate> 
      <EndDate> 
      <AnyDate>2002-04-30</AnyDate> 
      </EndDate> 
     </PositionHistory> 
     </EmployerOrg> 
    </EmploymentHistory> 
    </StructuredXMLResume> 
</Resume> 
+1

Вместо использования REXML используйте [Nokogiri] (http://nokogiri.org), который является стандартом defacto для разбора XML/HTML с Ruby и имеет красивый генератор, используя его [Builder] (http: // www .rubydoc.info/github/sparklemotion/nokogiri/Nokogiri/XML/Builder). –

+0

defacto стандарт? REXML находится в stdlib, и я бы хотел избежать добавления новой зависимости. – doremi

+1

@theTinMan, я думаю, что вы правы в популярности, SO может быть приблизительным ориентиром для оценки популярности (120 q, 2 последователя для REXML и 2557 q. С 135 последователями для Nokogiri). Хотя предлагать другой инструмент для выполнения этой работы не всегда является подходящим ответом ... – Abel

ответ

1

Возможно потому, что ваш XPath '//Title' говорит, чтобы начать в верхней части документа, почти игнорируя контекст-узел position_history. Попробуйте заменить это на './Title' или просто 'Title'.

+0

Кажется правильным наблюдением за мной, пятно на! :) – Abel

+0

Работа '' Title'' и '../Title''. Благодаря! Было бы интересно узнать, почему '//' начинается в верхней части документа, а не в контексте, в котором я прошел. Это то, что сработало. – doremi

+1

Поскольку документ обрабатывается только один раз, а функции возвращают то, что вы должны рассматривать указатели или наборы указателей на узлы в этом анализируемом документе. Вы можете думать об этом, как будто вы думаете о своем текущем рабочем каталоге в командной строке. если я скажу (формат Unix) 'ls /', он будет перечислять корневой каталог независимо от того, где в дереве файловой системы я есть. – bjimba