2016-08-28 3 views
0

Я использую nokogiri для доступа к XML-документу документа docx.Доступ к глубокому вложенному узлу из document.xml с помощью nokogiri

вот пример этого:

<w:document> 
    <w:body> 
     <w:p w:rsidR="00454EDC" w:rsidRDefault="00454EDC" w:rsidP="00454EDC"> 
       <w:drawing> 
        <wp:inline distT="0" distB="0" distL="0" distR="0"> 
         <wp:extent cx="1926590" cy="1088571"/> 
         <wp:effectExtent l="0" t="0" r="0" b="0"/> 
         <wp:docPr id="1" name="Picture 1"/> 
         <wp:cNvGraphicFramePr> 
          <a:graphicFrameLocks xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" noChangeAspect="1"/> 
         </wp:cNvGraphicFramePr> 
         <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main"> 
          <a:graphicData uri="http://schemas.openxmlformats.org/drawingml/2006/picture"> 
           <pic:pic xmlns:pic="http://schemas.openxmlformats.org/drawingml/2006/picture"> 
            <pic:nvPicPr> 
             <pic:cNvPr id="0" name="Picture 1"/> 
             <pic:cNvPicPr> 
              <a:picLocks noChangeAspect="1" noChangeArrowheads="1"/> 
             </pic:cNvPicPr> 
            </pic:nvPicPr> 
            <pic:blipFill> 
             <a:blip r:embed="rId5" cstate="print"> 
              <a:extLst> 
               <a:ext uri="{28A0092B-C50C-407E-A947-70E740481C1C}"> 
                <a14:useLocalDpi xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main" val="0"/> 
               </a:ext> 
              </a:extLst> 
             </a:blip> 
             <a:srcRect/> 
             <a:stretch> 
              <a:fillRect/> 
             </a:stretch> 
            </pic:blipFill> 
            <pic:spPr bwMode="auto"> 
             <a:xfrm> 
              <a:off x="0" y="0"/> 
              <a:ext cx="1951299" cy="1102532"/> 
             </a:xfrm> 
             <a:prstGeom prst="rect"> 
              <a:avLst/> 
             </a:prstGeom> 
             <a:noFill/> 
             <a:ln> 
              <a:noFill/> 
             </a:ln> 
            </pic:spPr> 
           </pic:pic> 
          </a:graphicData> 
         </a:graphic> 
        </wp:inline> 
       </w:drawing> 
      </w:p> 
    </w:body> 
</w:document> 

Теперь я хочу, чтобы получить доступ ко всем <w:drawing> тегов и из них я тусклый, чтобы получить доступ <a:blip> тегов и извлечь значение атрибута г: встраивать от него.

В этом случае, как вы можете видеть, что это rId5

Я могу получить доступ к <w:drawing> тег с помощью xml.xpath('//w:drawing'), но когда я делаю так xml.xpath('//w:drawing').xpath('//a:blip'), он выдает ошибку:

Nokogiri::XML::XPath::SyntaxError: Undefined namespace prefix: //a:blip 

Что я Я делаю неправильно, может ли кто-нибудь указать мне в правильном направлении?

ответ

1

ошибка говорит вам, что в вашем XPath запроса, //a:blip, Nokogiri Безразлично» t знать, к чему относится пространство имен a. Вам нужно указать те пространства имен, которые вы нацеливаете в своем запросе, а не только префикс. Тот факт, что префикс a определен в документе, не имеет особого значения, это важный URI-адрес пространства имен. В запросе можно использовать совершенно разные префиксы, чем те, которые используются в документе, если совпадают URI пространства имен.

Возможно, вам интересно, почему работает запрос //w:drawing. Вы не включаете полный XML, но я подозреваю, что префикс w определен в корневом узле (что-то вроде xmlns:w="http://some.uri.here"). Если вы не укажете пространства имен, Nokogiri автоматически зарегистрирует все, что определено в корневом узле, чтобы они были доступны в вашем запросе. Пространство имен, соответствующее префиксу a, не определено в корне, поэтому оно недоступно, и вы получаете сообщение об ошибке.

Чтобы указать пространство имен в Nokogiri вы передаете хэш, отображение префикса (используемый в запросе ) для URI пространства имен, к xpath метода (или который когда-либо метод запроса вы используете). Поскольку вы предоставляете свои собственные сопоставления пространства имен, вам также необходимо включить все, что вы используете из корневого узла, Nokogiri не включает их в этом случае.

В вашем случае код будет выглядеть примерно так:

namespaces = { 
    'w' => 'http://some.uri', # whatever the URI is for this namespace 
    'a' => 'http://schemas.openxmlformats.org/drawingml/2006/main' 
} 

# You can combine this to a single query. 
# Also note you don’t want a double slash infront of 
# the `/a:blip` part, just one. 
xml.xpath('//w:drawing/a:blip', namespaces) 

Посмотрите на Nokogiri tutorial section on namespaces для получения дополнительной информации.

+0

Отличное объяснение для новичка, как я, спасибо тонну человека :) – adil

1

Я бы сказал, что это ошибка в XML-парсер, который вы используете:

Действительно, ошибка, кажется, что префикс пространства имен a не определено, однако, оно было определено в <a:graphic xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">, который является родителем элемента <a:blip>.

See here if you want to know more about xml namespaces

Кажется, что они несколько другие вопросы о проблемах с префиксов в nokogiri, например: Undefined namespace prefix in Nokogiri and XPath

Смежные вопросы