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>
1 ответ
Это возможно даже с XSLT?
Да, он предназначен для таких задач.
Может кто-нибудь привести меня к тому, что мне нужно прочитать?
Если вы новичок в XSLT, это видеоурок от Dimitre Novatchev очень хорошее введение в XSLT и избавит вас от многих проблем. Это несколько долларов или несколько часов, проведенных очень хорошо.
Начиная с тега поля данных =550
То есть:
<xsl:template match="datafield[@tag = '550']">...
... с кодом подполя дочернего узла a,
То есть:
<xsl:template match="datafield[@tag = '550'][subfield[@code = 'a']]">...
Я хочу добавить значение тега контрольного поля 001
Т.е., предполагая, что фокус от предыдущего соответствующего шаблона:
<xsl:value-of select="../controlfield[@tag = '001']" />
на основе тега поля данных 151 код подполя а.
поскольку datafield
элементы кажутся родными братьями controlfield
(Я предполагаю, что за каждым контрольным полем следует набор полей данных), я собираюсь предположить, что они должны быть среди следующих братьев и сестер, но перед следующим контрольным полем, но адаптироваться к вашим потребностям.
То есть:
<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, который обеспечивает большую свободу выражения, комментарии внутри выражений (то есть так называемые smiley-comments, (:...:)
) и имеет больше способов для проверки (в этом случае, например, если один элемент лежит перед другим в порядке документа: <<
а также >>
операторы).
В данном случае это "2".
Выше код не проверен (ваши требования слишком сложны, и я боюсь, что я их неправильно понимаю), но, вероятно, это что-то в этом роде.
Тэг поля данных для сопоставления также может быть 150 в некоторых случаях.
В каких случаях вы должны настроить соответственно.
Я думаю о "ключах", но может быть и другой.
Да, это может помочь, но это зависит от остальных требований, если это действительно необходимо (см. Примеры выше).