使用XSLT选择和连接特定字符串

时间:2014-05-25 07:22:01

标签: xml xslt foreach

我有成千上万的MarcXML记录,我需要从每条记录中选择和连接特定的字符串。不幸的是,我似乎只能让我的XSLT表从文件中每个MarcXML记录的第一条记录中获取相同的字符串。

我所拥有的MarcXML记录是这样的:

<?xml version="1.0" encoding="UTF-8" ?> 
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">
<marc:record>
<marc:leader>01195cam a2200301 a 4500</marc:leader> 
<marc:datafield tag="100" ind1="1" ind2="">
<marc:subfield code="a">Bache, Franklin,</marc:subfield> 
<marc:subfield code="d">1792-1864.</marc:subfield> 
</marc:datafield>
<marc:datafield tag="245" ind1="1" ind2="3">
<marc:subfield code="a">An obituary notice of Thomas T. Hewson, M. D. :</marc:subfield> 
<marc:subfield code="h">[electronic resource]</marc:subfield> 
<marc:subfield code="b">late president of the Philadelphia College of Physicians
</marc:subfield> 
<marc:subfield code="c">by Franklin Bache ; read before the college, November 6, 1849 ; and published by its direction.</marc:subfield> 
</marc:datafield>
<marc:datafield tag="260" ind1="" ind2="">
<marc:subfield code="a">Philadelphia :</marc:subfield> 
<marc:subfield code="b">Geddes,</marc:subfield> 
<marc:subfield code="c">1850.</marc:subfield> 
</marc:datafield>
</marc:record>

<marc:record>
<marc:leader>01429cam a2200325 a 4500</marc:leader> 
</marc:datafield>
<marc:datafield tag="110" ind1="2" ind2="">
<marc:subfield code="a">American Public Health Association.</marc:subfield> 
<marc:subfield code="b">Committee on the Prevention of Venereal Diseases.</marc:subfield> 
</marc:datafield>
<marc:datafield tag="245" ind1="1" ind2="0">
<marc:subfield code="a">Report of the Committee on the Prevention of Venereal Diseases :</marc:subfield> 
<marc:subfield code="h">[electronic resource]</marc:subfield> 
<marc:subfield code="b">presented at the eighth annual meeting of the American Public Health Association, New Orleans, La., Nov. 7-10, 1880.</marc:subfield> 
</marc:datafield>
<marc:datafield tag="260" ind1="" ind2="">
<marc:subfield code="a">Boston :</marc:subfield> 
<marc:subfield code="b">Franklin,</marc:subfield> 
<marc:subfield code="c">1881.</marc:subfield> 
</marc:datafield>
</marc: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="text" encoding="UTF-8" indent="no" /> 
- <xsl:template match="marc:collection">
- <xsl:for-each select="marc:record">
- <xsl:choose>
- <xsl:when test="contains(//marc:leader, 'cam')">
  <xsl:call-template name="Title" /> 
  <xsl:call-template name="Date" /> 
  </xsl:when>
  </xsl:choose>
  </xsl:for-each>
  </xsl:template>
- <xsl:template name="Title">
  <xsl:variable name="short" select="//marc:datafield[@tag=245]/marc:subfield[@code='a']" /> 
  <xsl:value-of select="substring($short,1,20)" /> 
  </xsl:template>
- <xsl:template name="Date">
  <xsl:variable name="dd" select="//marc:datafield[@tag=260]/marc:subfield[@code='c']" /> 
  <xsl:value-of select="substring($dd,1,4)" /> 
  </xsl:template>
  </xsl:stylesheet>

我希望输出类似于:

An obituary notice of1850
Report of the Committ1881

但我获得了第一个字符串的两倍。 我试过不使用<xsl:for-each>,但结果是一样的。我可以解析每条记录的唯一方法是使用模板,但这不允许我选择特定的字符串。 任何人都可以帮助我吗?

1 个答案:

答案 0 :(得分:2)

您遇到的问题是背景。在XPath的开头不需要使用//。那是查询整个文档。在XSLT 1.0中,您只获得第一个结果。这就是你第二次看到第一根弦的原因。

这是样式表的更新版本。我删除了//并更改了“标题”substring()(以获取示例中的输出)。我还添加了换行符(&#xA;)。

更新了XSLT 1.0

<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="text" encoding="UTF-8" indent="no"/>
    <xsl:template match="marc:collection">
        <xsl:for-each select="marc:record">
            <xsl:choose>
                <xsl:when test="contains(marc:leader, 'cam')">
                    <xsl:call-template name="Title"/>
                    <xsl:call-template name="Date"/>
                    <xsl:text>&#xA;</xsl:text>
                </xsl:when>
            </xsl:choose>
        </xsl:for-each>
    </xsl:template>

    <xsl:template name="Title">
        <xsl:variable name="short" select="marc:datafield[@tag=245]/marc:subfield[@code='a']"/>
        <xsl:value-of select="substring($short,1,21)"/>
    </xsl:template>

    <xsl:template name="Date">
        <xsl:variable name="dd" select="marc:datafield[@tag=260]/marc:subfield[@code='c']"/>
        <xsl:value-of select="substring($dd,1,4)"/>
    </xsl:template>

</xsl:stylesheet>

你可以摆脱额外的模板。我就是这样做的:

XSLT 1.0

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:marc="http://www.loc.gov/MARC21/slim"
    exclude-result-prefixes="marc">
    <xsl:output method="text" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="/*">
        <xsl:apply-templates select="marc:record[contains(marc:leader, 'cam')]"/>
    </xsl:template>

    <xsl:template match="marc:record">
        <xsl:value-of select="substring(marc:datafield[@tag=245]/marc:subfield[@code='a'],1,21)"/>
        <xsl:value-of select="substring(marc:datafield[@tag=260]/marc:subfield[@code='c'],1,4)"/>
        <xsl:text>&#xA;</xsl:text>        
    </xsl:template>

</xsl:stylesheet>

这两个都会给你以下输出:

An obituary notice of1850
Report of the Committ1881