2015-08-07 2 views
0

Этот вопрос был значительно отредактирован, чтобы сделать вещи немного яснее.XPath для анализа eCFR XML с использованием атрибутов и узлов

Я пытаюсь вытащить данные из электронного кодекса федеральных правил XML-фида (http://www.gpo.gov/fdsys/bulkdata/CFR/2015/title-15/CFR-2015-title15-vol2.xml), и у меня возникли проблемы.

В частности, я хотел бы получить данные, которые будут сопоставляться комбинацией Узел и Атрибут. В следующем фрагменте XML вы можете увидеть некоторый текст, который я хотел бы захватить. Я хотел бы получить данные для каждого узла FP, где присутствует атрибут FP-2. Я также хотел бы захватить данные для каждого узла FP, имеющего атрибут FP-1.

<APPENDIX> 
 
       <EAR>Pt. 774, Supp. 1</EAR> 
 
       <HD SOURCE="HED">Supplement No. 1 to Part 774—The Commerce Control List</HD> 
 
       <HD SOURCE="HD1">Category 0—Nuclear Materials, Facilities, and Equipment [and Miscellaneous Items]</HD> 
 
       <HD SOURCE="HD1">A. “End Items,” “Equipment,” “Accessories,” “Attachments,” “Parts,” “Components,” and “Systems”</HD> 
 
       <FP SOURCE="FP-2"> 
 
       <E T="02">0A002Power generating or propulsion equipment “specially designed” for use with space, marine or mobile “nuclear reactors”. (These items are “subject to the ITAR.” See 22 CFR parts 120 through 130.)</E> 
 
       </FP> 
 
       
 
       <FP SOURCE="FP-2"> 
 
       <E T="02">0A018Items on the Wassenaar Munitions List (see List of Items Controlled).</E> 
 
       </FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="04">License Requirements</E> 
 
       </FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="03">Reason for Control:</E> NS, AT, UN</FP> 
 
       <GPOTABLE CDEF="s50,r50" COLS="2" OPTS="L2"> 
 
       <BOXHD> 
 
        <CHED H="1">Control(s)</CHED> 
 
        <CHED H="1">Country Chart (See Supp. No. 1 to part 738)</CHED> 
 
       </BOXHD> 
 
       <ROW> 
 
        <ENT I="01">NS applies to entire entry</ENT> 
 
        <ENT>NS Column 1.</ENT> 
 
       </ROW> 
 
       <ROW> 
 
        <ENT I="01">AT applies to entire entry</ENT> 
 
        <ENT>AT Column 1.</ENT> 
 
       </ROW> 
 
       <ROW> 
 
        <ENT I="01">UN applies to entire entry</ENT> 
 
        <ENT>See § 746.1(b) for UN controls.</ENT> 
 
       </ROW> 
 
       </GPOTABLE> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="05">List Based License Exceptions (See Part 740 for a description of all license exceptions)</E> 
 
       </FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="03">LVS:</E> $3,000 for 0A018.b</FP> 
 
       <FP SOURCE="FP-1">$1,500 for 0A018.c and .d</FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="03">GBS:</E> N/A</FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="03">CIV:</E> N/A</FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="04">List of Items Controlled</E> 
 
       </FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="03">Related Controls:</E> (1) See also 0A979, 0A988, and 22 CFR 121.1 Categories I(a), III(b-d), and X(a). (2) See ECCN 0A617.y.1 and .y.2 for items formerly controlled by ECCN 0A018.a. (3) See ECCN 1A613.c for military helmets providing less than NIJ Type IV protection and ECCN 1A613.y.1 for conventional military steel helmets that, immediately prior to July 1, 2014, were classified under 0A018.d and 0A988. (4) See 22 CFR 121.1 Category X(a)(5) and (a)(6) for controls on other military helmets.</FP> 
 
       <FP SOURCE="FP-1"> 
 
       <E T="03">Related Definitions:</E> N/A</FP> 
 
       <FP> 
 
       <E T="03">Items:</E> a. [Reserved]</FP> 
 
       <P>b. “Specially designed” components and parts for ammunition, except cartridge cases, powder bags, bullets, jackets, cores, shells, projectiles, boosters, fuses and components, primers, and other detonating devices and ammunition belting and linking machines (all of which are “subject to the ITAR.” (See 22 CFR parts 120 through 130);</P> 
 
       <NOTE> 
 
       <HD SOURCE="HED"> 
 
        <E T="03">Note:</E> 
 
       </HD> 
 
       <P> 
 
        <E T="03">0A018.b does not apply to “components” “specially designed” for blank or dummy ammunition as follows:</E> 
 
       </P> 
 
       <P> 
 
        <E T="03">a. Ammunition crimped without a projectile (blank star);</E> 
 
       </P> 
 
</APPENDIX>

Чтобы усложнить дело, я пытаюсь вытащить эти данные в Filemaker, но после редактирования, я буду придерживаться простого XSL.

Следующие XSL захватывают все узлы FP без дифференциации.

<?xml version='1.0' encoding='UTF-8'?> 
 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
 
<xsl:template match="/"> 
 
<xsl:for-each select="//FP"> 
 
<xsl:value-of select="."/> 
 
</xsl:for-each> 
 
</xsl:template> 
 
</xsl:stylesheet>

Изменение этого для соответствия XSL: матч шаблон = "FP [@ SOURCE = 'FP-1'] позволяет мне сделать необходимый матч на основе атрибута, но я м до сих пор не ясно, о том, как захватить нужные мне данные Мысли

+0

Просьба указать ** минимальный, но полный пример ** вашего входного XML. Никто не хочет пробираться через линии 70k. Затем уточните, какие узлы в источнике должны создать ** запись ** и какие данные попадают в какое поле в этой записи. В настоящее время ваша «таблица стилей» создает единую запись. Я помещал «таблицу стилей» в кавычки, потому что это не так. –

ответ

2

несколько вещей:.?

  1. Ваш XSLT на самом деле это не формат XSLT
  2. В XPath для ссылки на атрибут (то есть SOURCE), он должен иметь префикс @.
  3. И, наконец, есть много FP1 и FP2, но ваша настройка выбирает только первые экземпляры.

Рассмотрим следующий XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
<xsl:output version="1.0" encoding="UTF-8"/> 

<xsl:template match="/"> 
    <FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult"> 

    <METADATA> 
     <FIELD NAME="ECCNFP_2" TYPE="TEXT"/> 
    <FIELD NAME="ECCNFP_1" TYPE="TEXT"/> 
    </METADATA> 

    <RESULTSET> 

    <xsl:for-each select="//FP[@SOURCE = 'FP-2']/E[@T='02']"> 
    <ROW> 
     <COL> 
      <DATA><xsl:value-of select="substring(.,1,5)"/></DATA> 
     </COL> 
    </ROW> 
    </xsl:for-each>  

    <xsl:for-each select="//FP[@SOURCE = 'FP-1']/E[@T='02']"> 
    <ROW> 
     <COL> 
      <DATA><xsl:value-of select="substring(.,1,5)"/></DATA> 
     </COL> 
    </ROW> 
    </xsl:for-each>   

    </RESULTSET> 
</FMPXMLRESULT> 

</xsl:template> 
</xsl:stylesheet> 

Какой бы выход:

<?xml version='1.0' encoding='UTF-8'?> 
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult"> 
    <METADATA> 
    <FIELD NAME="ECCNFP_2" TYPE="TEXT"/> 
    <FIELD NAME="ECCNFP_1" TYPE="TEXT"/> 
    </METADATA> 
    <RESULTSET> 
    <ROW> 
     <COL> 
     <DATA>0A002</DATA> 
     </COL> 
    </ROW> 
    <ROW> 
     <COL> 
     <DATA>0A018</DATA> 
     </COL> 
    </ROW> 
    </RESULTSET> 
</FMPXMLRESULT> 

И частичный выход полный веб-ссылки XML:

<?xml version='1.0' encoding='UTF-8'?> 
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult"> 
    <METADATA> 
    <FIELD NAME="ECCNFP_2" TYPE="TEXT"/> 
    <FIELD NAME="ECCNFP_1" TYPE="TEXT"/> 
    </METADATA> 
    <RESULTSET> 
    <ROW> 
     <COL> 
     <DATA>2A000</DATA> 
     </COL> 
    </ROW> 
    <ROW> 
     <COL> 
     <DATA>0A002</DATA> 
     </COL> 
    </ROW> 
    <ROW> 
     <COL> 
     <DATA>0A018</DATA> 
     </COL> 
    </ROW> 
    <ROW> 
     <COL> 
     <DATA>0A521</DATA> 
     </COL> 
    </ROW> 
    <ROW> 
     <COL> 
     <DATA>0A604</DATA> 
     </COL> 
    </ROW> 
    <ROW> 
     <COL> 
     <DATA>0A606</DATA> 
     </COL> 
    </ROW> 
    ... 

В самом деле, указать свой XSLT-процессор к линии GPO и всем выходам FP1 и FP2. Я просто сделал это с Python! Близко к 3000 линиям!

+1

Вы создаете 3 узла COL, когда определены только 2 поля. –

+0

@ michael.hor257k, но см. Исходный XML-документ OP, существует два экземпляра ''. Предполагалось ли ОП для двух COL для одного узла ROW? Согласно OP: «Я хотел бы получить данные для каждого узла FP, где присутствует атрибут FP-2. Я также хотел бы захватить данные для каждого узла FP, имеющего атрибут FP-1». Тысячи выпусков COLs с полным веб-ссылкой. – Parfait

+0

"* Был ли OP предназначен для двух COLs для узла ROW? *" OP определил два поля, поэтому предположительно, что * - это намерение OP. Конечно, «тысячи COLs» ни для чего не полезны. Вот почему я попросил ОП уточнить. В любом случае, если вы попытаетесь импортировать свой результат, вы обнаружите, что содержимое третьего COL отбрасывается. –

0

Ваш вопрос еще не ясен. Если я сосредоточиться на этой части:

Я хотел бы получить данные для каждого узла FP, где атрибут FP-2 присутствует. Я также хотел бы захватить данные для каждого узла FP , имеющего атрибут FP-1.

, то вы, вероятно, хотите, чтобы это изменить:

<xsl:for-each select="//FP"> 

к:

<xsl:for-each select="//FP[@SOURCE='FP-1' or @SOURCE='FP-2']"> 

Обратите внимание, что это возвращает значение каждого элемента FP, где SOURCE атрибут имеет значение «FP-1» или «FP-2». Я не вижу «узел FP, где присутствует атрибут FP-2».

Обратите внимание, что синтаксис // является дорогостоящим с точки зрения вычислительной мощности. Если вы используете полный, явный путь, вы получите лучшую производительность.

+0

Моя первая проблема заключалась в написании типа оператора select, который вы только что предоставили. Незадолго до того, как я покинул свой офис, я, наконец, ударил по правильному синтаксису и смог получить вашу рекомендацию. Parfait проанализировал первый бит данных, который мне нужен выше. Теперь мне нужно будет сделать то же самое для тех узлов FP с атрибутом FP-1, но только те, которые также содержат узел/строку «E T =« 03 »>« Причина для управления:

+0

@ CJ Я боюсь, что мы не будем продвигаться вперед, если вы не четко укажете свою цель. Как минимум, отредактируйте свой вопрос и добавьте ожидаемый результат преобразования вашего примера ввода. –