2012-11-13 116 views
4

我在写一个xslt样式表,将MARC-xml记录转换为FGDC-xml元数据。很多MARC字段在最后(句号,冒号,逗号等)都有多余的标点符号,我想删除它们。尽管如此,我不想删除全部标点符号。我的想法是编写一个如果声明和测试如果字段结束与指定的字符,然后将其删除,但我不知道:1)如果这是一个好方法,2)如何指定该模板处理。xslt删除结尾标点符号

编辑我的XSLT:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:marc="http://www.loc.gov/MARC21/slim" > 
<xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

<xsl:template match="/"> 
<xsl:for-each select="marc:collection/marc:record"> 
    <xsl:result-document method="xml" href="banana_{marc:controlfield[@tag=001]}.xml"> 
    <metadata> 
     <xsl:apply-templates select="self::marc:record"/> 
    </metadata> 
    </xsl:result-document> 
</xsl:for-each> 
</xsl:template> 

<xsl:template match="marc:record"> 
    <pubinfo> 
    <pubplace><xsl:value-of select="marc:datafield[@tag=260]/marc:subfield[@code='a']"/></pubplace> 
    <publish><xsl:value-of select="marc:datafield[@tag=260]/marc:subfield[@code='b']" /></publish> 
    </pubinfo> 
</xsl:template> 

</xsl:stylesheet> 

这里是我的xml文档(或至少它的代表性部分):

<?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>01502cfm a2200313 a 4500</marc:leader> 
    <marc:controlfield tag="001">7943586</marc:controlfield> 
    <marc:datafield tag="260" ind1=" " ind2=" "> 
     <marc:subfield code="a">[S.l. :</marc:subfield> 
     <marc:subfield code="b">s.n. ,</marc:subfield> 
     <marc:subfield code="c">18--]</marc:subfield> 
    </marc:datafield> 
</marc:record> 
<marc:record> 
    <marc:leader>01290cem a2200313 a 4500</marc:leader> 
    <marc:controlfield tag="001">8108664</marc:controlfield> 
    <marc:datafield tag="260" ind1=" " ind2=" "> 
     <marc:subfield code="a">Torino :</marc:subfield> 
     <marc:subfield code="b">Editore Gio. Batt. Maggi ,</marc:subfield> 
     <marc:subfield code="c">1863.</marc:subfield> 
    </marc:datafield> 
</marc:record> 
</marc:collection> 
+0

“不知道放在这里?” 'substring(1,string-length(marc:datafield [@ tag = 260]/marc:subfield [@ code ='b']) - 1)'工作吗? – Pawel

+0

我会尽力......但首先我想我的测试语句的语法错误,但是,这阻止了正确编译样式表。我得到错误:“在令牌开始的意外冒号” –

+0

好吧,我想我找到了“意外冒号...”的错误,现在我有:''。请原谅我,如果这是一个愚蠢的问题@Pawel,但我应该在你的建议的东西附上一行吗?我试图插入它,它只返回一个空标签。 –

回答

4

ends-with()接受一个简单的字符串,而不是一个正则表达式。这就是为什么你有问题:

ends-with(marc:datafield[@tag=260]/marc:subfield[@code='b'],'.|:|,') 

如果你想使用正则表达式,然后使用matches()

marc:datafield[@tag=260]/marc:subfield[@code='b']/matches(.,'^.*[\.:,]$') 

,并删除使用replace()

replace('Ends with punctuation.', '^(.*)[\.:,]$', '$1') 
=> 
Ends with punctuation 

它也将可能会更简单,只是在每个节点上执行替换,而不是先用if进行测试,因为不匹配的情况不会进行替换,这似乎是行为无论如何你是想要的。

+0

啊哈!谢谢@wst,这很好用。 –

2

一个通用的解决方案存在,这并不需要预先知道什么都结束标点符号

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 

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

<xsl:template match="text()[matches(., '^.*\p{P}$')]"> 
    <xsl:sequence select="replace(., '(^.*)\p{P}$', '$1')"/> 
</xsl:template> 
</xsl:stylesheet> 

当这一转型是这个XML文档施加:

<x> 
    <t>Some text .</t> 
    <t>Some text2 ;</t> 
    <t>Some text3 (</t> 
    <t>Some text4 !</t> 
    <t>Some text5 "</t> 
</x> 

想要的,正确的结果产生:

<x> 
     <t>Some text </t> 
     <t>Some text2 </t> 
     <t>Some text3 </t> 
     <t>Some text4 </t> 
     <t>Some text5 </t> 
</x> 

说明

正确使用p{P}字符类/类别。

\p是为跳转为标点类别。 P所有标点符号属性。

更新

的OP提供特定的源XML文档和她的转换代码。

这里是她的代码,用上述溶液修改:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:marc="http://www.loc.gov/MARC21/slim" > 
<xsl:output method="xml" encoding="UTF-8" indent="yes"/> 

<xsl:template match="/"> 
<xsl:for-each select="marc:collection/marc:record"> 
    <xsl:result-document method="xml" href="banana_{marc:controlfield[@tag=001]}.xml"> 
    <metadata> 
     <xsl:apply-templates select="self::marc:record"/> 
    </metadata> 
    </xsl:result-document> 
</xsl:for-each> 
</xsl:template> 

<xsl:template match="marc:record"> 
    <pubinfo> 
    <xsl:variable name="vSub1" select="marc:datafield[@tag=260]/marc:subfield[@code='a']"/> 
    <xsl:variable name="vSub2" select="marc:datafield[@tag=260]/marc:subfield[@code='b']"/> 
    <pubplace><xsl:value-of select="replace($vSub1, '(^.*)\s\p{P}$', '$1')"/></pubplace> 
    <publish><xsl:value-of select="replace($vSub2, '(^.*)\s\p{P}$', '$1')" /></publish> 
    </pubinfo> 
</xsl:template> 

</xsl:stylesheet> 
+0

谢谢你的额外答案。我想我理解逻辑,但是我很难正确实施它。我有一些其他模板指定输出如下:''那可以吗?是否会影响其他模板的表现?我还想知道是否有办法在结束标点符号的同时消除尾随空格。 –

+0

@SusanPowell,人们不应该猜测你的确切代码或XML文档是什么 - 欢迎你编辑问题并提供更多可代表的代码+数据。至于消除尾随空白,只需使用:''^。* \ s \ p {P} $''而不是''^ \ * p {P} $'' –

+0

对不起,我是新来的并忘记我可以编辑我的原始帖子:$现在更新更完整的代码。同样感谢您提供有关清除尾部空白的答案。 –