xsl 从另一个节点树获取元素值 [英] xsl get element values from another node tree

查看:16
本文介绍了xsl 从另一个节点树获取元素值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下 XML:

<记录><leader>01877nz a2200433o 4500</leader><controlfield tag="001">1</controlfield><datafield tag="013" ind1="" ind2=""><subfield code="a">formerge</subfield></数据字段>...<datafield tag="150" ind1="" ind2=""><subfield code="a">Borneo</subfield></数据字段>...<datafield tag="550" ind1="" ind2=""><subfield code="w">g</subfield><subfield code="a">东南亚</subfield><subfield code="c">c_7260</subfield></数据字段>...</记录>...<记录>......</记录><记录><leader>02462nz a2200553o 4500</leader><controlfield tag="001">2</controlfield>...<datafield tag="013" ind1="" ind2=""><subfield code="a">formerge</subfield></数据字段><datafield tag="035" ind1="" ind2=""><subfield code="a">c_7260</subfield></数据字段>...<datafield tag="151" ind1="" ind2=""><subfield code="a">东南亚</subfield></数据字段>...</记录>

从datafield tag=550开始,子节点subfield code a,我想根据datafield tag 151 subfield code a添加controlfield tag 001的值.在这种情况下,它是2".在某些情况下,要匹配的数据字段标记也可以是 150.节点树上的节点更多,但基本上如下所示:

<领导者>...</领导者><controlfield tag="001">..</controlfield>-->这个可以到 010<datafield tag="150" ind1="" ind2="">-->这个可以是从 011 到 999<subfield code="a">..</subfield>-->属性可以是 0-9,a-z...</子字段></数据字段></记录>

所以我仍然想保留 xml,因为它刚刚添加了我想要的值,如下所示:

<代码> ...<datafield tag="150" ind1="" ind2=""><subfield code="a">Borneo</subfield></数据字段>...<datafield tag="550" ind1="" ind2=""><subfield code="w">g</subfield><subfield code="a">东南亚</subfield><subfield code="c">c_7260</subfield><subfield code="0">2</subfield></数据字段>

这甚至可以用 XSLT 实现吗?有人可以引导我了解我需要阅读的内容吗?我在想钥匙",但可能还有另一个.提前致谢!

更新:我有以下模板,我添加了 Abel 的代码:

<xsl:output method="xml" encoding="UTF-8" indent="yes"/><xsl:template match="/"><xsl:apply-templates/><xsl:apply-templates select="//datafield"/></xsl:模板><xsl:template match="@*|node()"><xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy></xsl:模板><xsl:variable name="next-ctl" select="生成 ID(../控制字段[@tag = '001']/following-sibling::controlfield[1])"/><xsl:template match="//datafield[@tag = '550'][subfield[@code = 'a']]"><xsl:value-of select="../controlfield[@tag = '001'][以下兄弟姐妹::数据字段[@tag = '151'][子字段[@code = 'a']][以下兄弟姐妹::控制字段[generate-id(.) = $next-ctl与否(以下兄弟姐妹::控制字段)]]]"/></xsl:模板>

解决方案

这甚至可以用 XSLT 实现吗?

是的,它适用于此类任务.

<块引用>

有人可以引导我了解我需要阅读的内容吗?

如果您不熟悉 XSLT,Dimitre Novatchev 的这个视频教程是对 XSLT 的非常好的介绍,将为您省去很多麻烦.花几美元或几个小时就很值得了.

<块引用>

从数据字段 tag=550 开始

即:

...

<块引用>

... 带有子节点子字段代码 a,

即:

...

<块引用>

我想添加 controlfield 标签的值 001

即,假设焦点来自之前的匹配模板:

<块引用>

基于数据字段标记 151 子字段代码 a.

由于 datafield 元素似乎是 controlfield 的兄弟元素(我假设每个 controlfield 后跟一组数据字段),我将假设它们必须在跟随兄弟姐妹,但在下一个控制字段之前,但要根据您的需要进行调整.

即:

<xsl:value-of select="../控制字段[@tag = '001'][以下兄弟姐妹::数据字段[@tag = '151'][子字段[@code = 'a']][以下兄弟姐妹::控制字段[generate-id(.) = $next-ctl与否(以下兄弟姐妹::控制字段)]]]"/>

注意:如果表达式变得像这些一样复杂,并且简化不是微不足道的(即拆分和使用变量),您可以考虑切换到XSLT 2.0,它允许更多的表达自由,表达式中的注释(即所谓的笑脸-comments, (:...:)) 并有更多的测试方法(在这种情况下,例如,如果一个元素按文档顺序位于另一个元素之前:<<>> 运算符).

<块引用>

在这种情况下,它是2".

以上代码未经测试(您的要求太复杂,我担心我误解了它们),但可能是这些方面的内容.

<块引用>

在某些情况下,要匹配的数据字段标记也可以是 150.

在哪些情况下您应该相应地进行调整.

<块引用>

我在想钥匙",但可能还有另一个.

是的,这可能会有所帮助,但这取决于其他要求是否实际需要(参见上面的示例).

I have the following 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>

Starting from datafield tag=550 with child node subfield code a, I want to add the value of controlfield tag 001 based on datafield tag 151 subfield code a. In this case, it's "2". The datafield tag to match to can also be 150 in some cases. There are more on nodes on the the node tree but basically it's like below:

<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>        

So I still wanted to keep the xml as is just added the value I want to get like below:

      ...
<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>

Is this even possible with XSLT? Can somebody please lead me to what I need to read up on? I'm thinking "keys" but there could be another one. Thanks in advance!

Update: I have the following templates, I added Abel's code:

<?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>

解决方案

Is this even possible with XSLT?

Yes, it is meant for tasks like this.

Can somebody please lead me to what I need to read up on?

If you are new to XSLT, this video tutorial by Dimitre Novatchev is a very good introduction on XSLT and will save you a lot of trouble. It's a few dollars or a few hours very well spent.

Starting from datafield tag=550

I.e.:

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

... with child node subfield code a,

I.e.:

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

I want to add the value of controlfield tag 001

I.e., assuming focus is from previous matching template:

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

based on datafield tag 151 subfield code a.

Since datafield elements appear to be siblings of controlfield (I assume each controlfield is followed by a set of datafields), I am going to assume they must be amongst the following siblings, but before the next controlfield, but adjust to your needs.

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)]
        ]
     ]" />

Note: if expressions become complex as these, and simplification is not trivial (i.e. splitting and using variables), you can consider switching to XSLT 2.0, which allows more freedom of expression, comments inside expressions (i.e. the so-called smiley-comments, (:...:)) and has more ways to test (in this case, for instance if one element lies before another one in document order: << and >> operators).

In this case, it's "2".

Above code not tested (your requirements are too complex and I fear I misunderstand them), but it is probably something along these lines.

The datafield tag to match to can also be 150 in some cases.

In which cases you should adjust accordingly.

I'm thinking "keys" but there could be another one.

Yes, this may help, but it depends on the rest of the requirements is this is actually needed (see examples above).

这篇关于xsl 从另一个节点树获取元素值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆