xslt删除结束标点符号

时间:2012-11-13 19:37:27

标签: xslt xslt-2.0

我正在编写一个xslt样式表来将MARC-xml记录转换为FGDC-xml元数据。很多MARC字段在末尾都有无关的标点符号(句号,冒号,逗号等),我想删除它们。不过,我不想从行中删除所有标点符号。我的想法是编写一个带有 if 语句的模板,并测试该字段是否以指定字符结尾,然后将其删除,但我不确定:1)如果这是一个好的方法,2 )如何指定该过程。

已修改我的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>

2 个答案:

答案 0 :(得分: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 first进行测试也可能更简单,因为不匹配的情况不会进行替换,这似乎就是你想要的行为。

答案 1 :(得分: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>