xsl получить значения элементов из другого дерева узлов

У меня есть следующий XML:

<?xml version="1.0" encoding="UTF-8"?>
 <collection
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.loc.gov/MARC21/slim..."
 xmlns="http://www.loc.gov/MARC21/slim">

 <record>
  <leader>01877nz  a2200433o  4500</leader>
  <controlfield tag="001">1</controlfield>
  <datafield tag="013" ind1=" " ind2=" ">
   <subfield code="a">formerge</subfield>
  </datafield>
          ...
  <datafield tag="150" ind1=" " ind2=" ">
   <subfield code="a">Borneo</subfield>
  </datafield>
          ...
  <datafield tag="550" ind1=" " ind2=" ">
   <subfield code="w">g</subfield>
   <subfield code="a">South East Asia</subfield>
   <subfield code="c">c_7260</subfield>
  </datafield>
       ...
  </record>

       ...

  <record>
       ...
       ...
  </record>

  <record>
   <leader>02462nz  a2200553o  4500</leader>
   <controlfield tag="001">2</controlfield>
         ...
   <datafield tag="013" ind1=" " ind2=" ">
    <subfield code="a">formerge</subfield>
   </datafield>
   <datafield tag="035" ind1=" " ind2=" ">
    <subfield code="a">c_7260</subfield>
   </datafield>
       ...
   <datafield tag="151" ind1=" " ind2=" ">
    <subfield code="a">South East Asia</subfield>
   </datafield>
       ...
  </record>

Начиная с тега поля данных = 550 с кодом подполя дочернего узла a, я хочу добавить значение тега поля управления 001 на основе кода подполя тега 151 поля данных a. В данном случае это «2». Тег поля данных для сопоставления также может быть равен 150 в некоторых случаях. В дереве узлов есть больше узлов, но в основном это выглядит следующим образом:

<record>
 <leader>...</leader>
 <controlfield tag="001">..</controlfield> --> this one can be up to 010
 <datafield tag="150" ind1=" " ind2=" "> --> this one can be from 011 to 999
  <subfield code="a">..</subfield> --> attributes can be 0-9, a-z
    ...
  </subfield>
 </datafield>
</record>        

Итак, я все еще хотел сохранить xml, так как просто добавил значение, которое я хочу получить, как показано ниже:

      ...
<datafield tag="150" ind1=" " ind2=" ">
 <subfield code="a">Borneo</subfield>
</datafield>
          ...
<datafield tag="550" ind1=" " ind2=" ">
 <subfield code="w">g</subfield>
 <subfield code="a">South East Asia</subfield>
 <subfield code="c">c_7260</subfield>
 <subfield code="0">2</subfield>
</datafield>

Возможно ли это даже с XSLT? Может ли кто-нибудь привести меня к тому, что мне нужно прочитать? Я думаю "ключи", но может быть и другой. Заранее спасибо!

Обновление: у меня есть следующие шаблоны, я добавил код Абеля:

<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0" xmlns:marc="http://www.loc.gov/MARC21/slim"     xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"    xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" exclude-result-prefixes="marc">
 <xsl:output method="xml" encoding="UTF-8" indent="yes"/>


  <xsl:template match="/">
   <xsl:apply-templates />
   <xsl:apply-templates select="//datafield"/>
  </xsl:template>

 <xsl:template match="@*|node()">
  <xsl:copy>
   <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template> 

<xsl:variable name="next-ctl" select="
 generate-id(
    ../controlfield[@tag = '001']
    /following-sibling::controlfield[1])" />

<xsl:template match="//datafield[@tag = '550'][subfield[@code = 'a']]">
 <xsl:value-of select="../controlfield[@tag = '001']
  [following-sibling::datafield
    [@tag = '151']
    [subfield[@code = 'a']]
    [following-sibling::controlfield
       [generate-id(.) = $next-ctl
       or not(following-sibling::controlfield)]
    ]
 ]" />
 </xsl:template>


person schnydszch    schedule 07.09.2015    source источник


Ответы (1)


Возможно ли это даже с XSLT?

Да, он предназначен для таких задач.

Может ли кто-нибудь привести меня к тому, что мне нужно прочитать?

Если вы новичок в XSLT, это видеоруководство Дмитрия Новатчева является очень хорошим введением в XSLT и избавит вас от многих проблем. Это несколько долларов или несколько часов, проведенных с пользой.

Начиная с тега поля данных = 550

I.e.:

<xsl:template match="datafield[@tag = '550']">...

... с кодом подполя дочернего узла a,

I.e.:

<xsl:template match="datafield[@tag = '550'][subfield[@code = 'a']]">...

Я хочу добавить значение тега controlfield 001

То есть, если предположить, что фокус находится в предыдущем соответствующем шаблоне:

<xsl:value-of select="../controlfield[@tag = '001']" />

на основе кода подполя тега 151 поля данных a.

Поскольку элементы datafield кажутся братьями и сестрами элемента controlfield (я предполагаю, что за каждым полем управления следует набор полей данных), я собираюсь предположить, что они должны быть среди следующих братьев и сестер, но перед следующим полем управления, но приспособьтесь к вашим потребностям.

I.e.:

<xsl:variable name="next-ctl" select="
     generate-id(
        ../controlfield[@tag = '001']
        /following-sibling::controlfield[1])" />

<xsl:value-of select="
     ../controlfield[@tag = '001']
     [following-sibling::datafield
        [@tag = '151']
        [subfield[@code = 'a']]
        [following-sibling::controlfield
           [generate-id(.) = $next-ctl
           or not(following-sibling::controlfield)]
        ]
     ]" />

Примечание: если выражения становятся такими сложными, а упрощение не является тривиальным (т. е. разделение и использование переменных), вы можете рассмотреть возможность перехода на XSLT 2.0, который предоставляет больше свободы выражения, комментарии внутри выражений (т. е. так называемые смайли-комментарии, (:...:)) и имеет больше способов проверки (в данном случае, например, если один элемент находится перед другим в порядке документа: операторы << и >>).

В данном случае это «2».

Приведенный выше код не тестировался (ваши требования слишком сложны, и я боюсь, что неправильно их понимаю), но, вероятно, это что-то в этом роде.

Тег поля данных для сопоставления также может быть равен 150 в некоторых случаях.

В каких случаях вы должны соответствующим образом скорректировать.

Я думаю "ключи", но может быть и другой.

Да, это может помочь, но это зависит от остальных требований, действительно ли это необходимо (см. примеры выше).

person Abel    schedule 07.09.2015
comment
Привет, Абель, теги поля управления вводятся только в первых строках сразу после лидера. И да, поля данных являются братьями и сестрами с полем управления. Что касается значений, которые я хочу получить, я хочу вставить в тег 550 подполе 0, которое является тегом поля управления 001 тега поля данных 150 или 151. Это 150 или 151 имеет то же значение, что и тег 550. А также деревья узлов могут быть в другом месте, а не последовательно или друг за другом. - person schnydszch; 07.09.2015
comment
@schnydszch, тогда мои предложения должны указать вам правильное направление, хотя, возможно, потребуется некоторая настройка. Они не зависят от порядка их появления. - person Abel; 07.09.2015
comment
Привет, Абель. Я добавил ваш ответ после копирования всех шаблонов. Я могу что-то упустить. ТИА! - person schnydszch; 08.09.2015