xslt 使用键和变量
xslt working with keys and variables
大家好,这个问题与此有关:xsl get element values from another node tree 但是这次我有一个可以工作的 xslt。
我目前正在研究以下 xml:
<record>
<leader>01877nz a2200433o 4500</leader>
<controlfield tag="001">1</controlfield>
... (more controlfields tag 002 to 010)
<datafield tag="013" ind1=" " ind2=" ">
<subfield code="a">formerge</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
<datafield tag="150" ind1=" " ind2=" ">
<subfield code="a">Borneo</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
<datafield tag="550" ind1=" " ind2=" ">
<subfield code="w">g</subfield>
<subfield code="a">South East Asia</subfield>
<subfield code="c">c_7260</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
</record>
... (more records)
<record>
... (more records fields)
... (more records fields)
</record>
<record>
<leader>02462nz a2200553o 4500</leader>
<controlfield tag="001">2</controlfield>
... (more controlfields tag 002 to 010)
<datafield tag="013" ind1=" " ind2=" ">
<subfield code="a">formerge</subfield>
</datafield>
<datafield tag="035" ind1=" " ind2=" ">
<subfield code="a">c_7260</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
<datafield tag="151" ind1=" " ind2=" ">
<subfield code="a">South East Asia</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
</record>
我有以下 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:key name="term" match="//datafield[@tag='151'][subfield[@code='a']]" use="." />
<xsl:template match="//datafield[@tag='151'][subfield[@code='a']]">
<xsl:variable name="t550a" select="//datafield[@tag='550'][subfield[@code='a']]" />
<xsl:for-each select="key('term','0a')">
<xsl:value-of select="//controlfield[@tag='001']" />
</xsl:for-each>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
有了这个,我通过键(术语)创建了所有 151 个索引。我还创建了一个变量 't550a'。通过 keys 函数,我将 550a 标签 (datafield tag="550" subfield code="a") 与 term key 匹配。然后获取该键的控制字段标记 001 的值。我还想获得 xml 的所有节点,从而获得 "xsl:copy"。使用我拥有的 xslt,似乎正在删除数据字段标记 151。
我想在 550 字段中获得以下内容:
... (other fields omitted)
<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>
... (other fields omitted)
<datafield tag="550" ind1=" " ind2=" ">
<subfield code="w">h</subfield>
<subfield code="a">Borneo</subfield>
<subfield code="c">c_1017</subfield>
<subfield code="0">1</subfield>
</datafield>
因此,550 个子字段 a South East Asia 将有附加的子字段 0,值为 2,它基于 151 个子字段 a South East Asia 的控制字段 001。婆罗洲 550 个子字段将有附加的值为 1 的子字段 0,它基于婆罗洲 151 个子字段的控制字段 001。
有人可以指导我正确地做这件事吗?谢谢!
With the xslt I have, it seems that datafield tag 151 is being removed.
是的,这是正确的,因为这是你指示它做的:
<xsl:template match="//datafield[@tag='151'][subfield[@code='a']]">
<xsl:variable name="t550a" select="//datafield[@tag='550'][subfield[@code='a']]" />
<xsl:for-each select="key('term','0a')">
<xsl:value-of select="//controlfield[@tag='001']" />
</xsl:for-each>
</xsl:template>
这意味着:当 datafield
匹配时,在每次迭代中遍历所有值为 0a
和 select(从根开始!)的所有控制字段值。我假设您更愿意使用当前节点的控制字段,例如 .//controlfield....
?
但是您没有在此处创建任何元素。如果你想要那个,你应该添加那个。即:
<xsl:template match="//datafield[@tag='151'][subfield[@code='a']]">
<xsl:variable name="t550a" select="//datafield[@tag='550'][subfield[@code='a']]" />
<xsl:copy>
<xsl:for-each select="key('term','0a')">
<xsl:value-of select="//controlfield[@tag='001']" />
</xsl:for-each>
</xsl:copy>
</xsl:template>
这将复制 datafield
。
我认为您的模板匹配了错误的元素。如果您希望将子节点添加到“550”字段,您应该有一个匹配的模板
<xsl:template match="datafield[@tag='550'][subfield[@code='a']]">
我也会稍微调整一下密钥,因为目前密钥也会使用空白节点(尽管如果您使用 xsl:strip-space
,这可能会被删除
<xsl:key name="term" match="datafield[@tag='151']" use="subfield[@code='a']" />
您遇到的下一个问题是您对 tt50a
变量的定义。你真的想在这里使用一个相对表达式,因为此刻它会在文档的任何地方找到第一个匹配的元素。你应该改为这样做(这是有效的,因为你现在位于 550
节点上)
<xsl:variable name="t550a" select="subfield[@code='a']" />
但是,您似乎并没有真正使用这个变量。您当前使用的键 key('term','0a')
是使用字符串文字,而不是变量。你可能是想这样做:
<xsl:for-each select="key('term',$t550a)">
最后,在您执行 //controlfield[@tag='001']
的 xsl:for-each
中,这 select 是文档中的第一个 controlfield
。我认为您只想 select 当前 record
中的那个。由于 record
是当前 datafield
的父级,您可以这样做:
<xsl:value-of select="../controlfield[@tag='001']" />
试试这个 XSLT
<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="rdf dc marc">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:key name="term" match="datafield[@tag='151']" use="subfield[@code='a']" />
<xsl:template match="datafield[@tag='550'][subfield[@code='a']]">
<xsl:variable name="t550a" select="subfield[@code='a']" />
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:for-each select="key('term',$t550a)">
<subfield code="0">
<xsl:value-of select="../controlfield[@tag='001']" />
</subfield>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这不会准确给出您在问题中显示的输出,因为您的输入 XML 只有一个 550
节点。
大家好,这个问题与此有关:xsl get element values from another node tree 但是这次我有一个可以工作的 xslt。
我目前正在研究以下 xml:
<record>
<leader>01877nz a2200433o 4500</leader>
<controlfield tag="001">1</controlfield>
... (more controlfields tag 002 to 010)
<datafield tag="013" ind1=" " ind2=" ">
<subfield code="a">formerge</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
<datafield tag="150" ind1=" " ind2=" ">
<subfield code="a">Borneo</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
<datafield tag="550" ind1=" " ind2=" ">
<subfield code="w">g</subfield>
<subfield code="a">South East Asia</subfield>
<subfield code="c">c_7260</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
</record>
... (more records)
<record>
... (more records fields)
... (more records fields)
</record>
<record>
<leader>02462nz a2200553o 4500</leader>
<controlfield tag="001">2</controlfield>
... (more controlfields tag 002 to 010)
<datafield tag="013" ind1=" " ind2=" ">
<subfield code="a">formerge</subfield>
</datafield>
<datafield tag="035" ind1=" " ind2=" ">
<subfield code="a">c_7260</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
<datafield tag="151" ind1=" " ind2=" ">
<subfield code="a">South East Asia</subfield>
</datafield>
... (more datafield tags, datafield tags are from 011 to 999)
</record>
我有以下 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:key name="term" match="//datafield[@tag='151'][subfield[@code='a']]" use="." />
<xsl:template match="//datafield[@tag='151'][subfield[@code='a']]">
<xsl:variable name="t550a" select="//datafield[@tag='550'][subfield[@code='a']]" />
<xsl:for-each select="key('term','0a')">
<xsl:value-of select="//controlfield[@tag='001']" />
</xsl:for-each>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
有了这个,我通过键(术语)创建了所有 151 个索引。我还创建了一个变量 't550a'。通过 keys 函数,我将 550a 标签 (datafield tag="550" subfield code="a") 与 term key 匹配。然后获取该键的控制字段标记 001 的值。我还想获得 xml 的所有节点,从而获得 "xsl:copy"。使用我拥有的 xslt,似乎正在删除数据字段标记 151。
我想在 550 字段中获得以下内容:
... (other fields omitted)
<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>
... (other fields omitted)
<datafield tag="550" ind1=" " ind2=" ">
<subfield code="w">h</subfield>
<subfield code="a">Borneo</subfield>
<subfield code="c">c_1017</subfield>
<subfield code="0">1</subfield>
</datafield>
因此,550 个子字段 a South East Asia 将有附加的子字段 0,值为 2,它基于 151 个子字段 a South East Asia 的控制字段 001。婆罗洲 550 个子字段将有附加的值为 1 的子字段 0,它基于婆罗洲 151 个子字段的控制字段 001。
有人可以指导我正确地做这件事吗?谢谢!
With the xslt I have, it seems that datafield tag 151 is being removed.
是的,这是正确的,因为这是你指示它做的:
<xsl:template match="//datafield[@tag='151'][subfield[@code='a']]">
<xsl:variable name="t550a" select="//datafield[@tag='550'][subfield[@code='a']]" />
<xsl:for-each select="key('term','0a')">
<xsl:value-of select="//controlfield[@tag='001']" />
</xsl:for-each>
</xsl:template>
这意味着:当 datafield
匹配时,在每次迭代中遍历所有值为 0a
和 select(从根开始!)的所有控制字段值。我假设您更愿意使用当前节点的控制字段,例如 .//controlfield....
?
但是您没有在此处创建任何元素。如果你想要那个,你应该添加那个。即:
<xsl:template match="//datafield[@tag='151'][subfield[@code='a']]">
<xsl:variable name="t550a" select="//datafield[@tag='550'][subfield[@code='a']]" />
<xsl:copy>
<xsl:for-each select="key('term','0a')">
<xsl:value-of select="//controlfield[@tag='001']" />
</xsl:for-each>
</xsl:copy>
</xsl:template>
这将复制 datafield
。
我认为您的模板匹配了错误的元素。如果您希望将子节点添加到“550”字段,您应该有一个匹配的模板
<xsl:template match="datafield[@tag='550'][subfield[@code='a']]">
我也会稍微调整一下密钥,因为目前密钥也会使用空白节点(尽管如果您使用 xsl:strip-space
<xsl:key name="term" match="datafield[@tag='151']" use="subfield[@code='a']" />
您遇到的下一个问题是您对 tt50a
变量的定义。你真的想在这里使用一个相对表达式,因为此刻它会在文档的任何地方找到第一个匹配的元素。你应该改为这样做(这是有效的,因为你现在位于 550
节点上)
<xsl:variable name="t550a" select="subfield[@code='a']" />
但是,您似乎并没有真正使用这个变量。您当前使用的键 key('term','0a')
是使用字符串文字,而不是变量。你可能是想这样做:
<xsl:for-each select="key('term',$t550a)">
最后,在您执行 //controlfield[@tag='001']
的 xsl:for-each
中,这 select 是文档中的第一个 controlfield
。我认为您只想 select 当前 record
中的那个。由于 record
是当前 datafield
的父级,您可以这样做:
<xsl:value-of select="../controlfield[@tag='001']" />
试试这个 XSLT
<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="rdf dc marc">
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>
<xsl:key name="term" match="datafield[@tag='151']" use="subfield[@code='a']" />
<xsl:template match="datafield[@tag='550'][subfield[@code='a']]">
<xsl:variable name="t550a" select="subfield[@code='a']" />
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
<xsl:for-each select="key('term',$t550a)">
<subfield code="0">
<xsl:value-of select="../controlfield[@tag='001']" />
</subfield>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
这不会准确给出您在问题中显示的输出,因为您的输入 XML 只有一个 550
节点。