【问题标题】:How to substitute a part of the line in XML with XSLT?如何用 XSLT 替换 XML 中的部分行?
【发布时间】:2018-01-16 17:30:36
【问题描述】:

我有以下 XML 文件:

<?xml version="1.0" encoding="UTF-8"?>
<mets:mets xmlns:mets="http://www.loc.gov/METS/">
 <mets:fileSec>
    <mets:fileGrp ID="rep1" ADMID="rep1-amd">
      <mets:file ID="fid1-1" ADMID="fid1-1-amd">
        <mets:FLocat xmlns:xlin="http://www.w3.org/1999/xlink" LOCTYPE="URL" xlin:href="/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams/MASTER/Prandtl_4.pdf"/>

      </mets:file>
    </mets:fileGrp>
    <mets:fileGrp ID="rep2" ADMID="rep2-amd">
      <mets:file ID="fid1-2" ADMID="fid1-2-amd">
        <mets:FLocat xmlns:xlin="http://www.w3.org/1999/xlink" LOCTYPE="URL" xlin:href="/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams/DERIVATIVE_COPY/631313192.pdf"/>
      </mets:file>
    </mets:fileGrp>
  </mets:fileSec>
</mets:mets> 

对于每个 mets:FLocat 我想做以下更改:

现在: &lt;mets:FLocat xmlns:xlin="http://www.w3.org/1999/xlink" LOCTYPE="URL" xlin:href="/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams/MASTER/Prandtl_4.pdf"/&gt;

必须是:&lt;mets:FLocat LOCTYPE="URL" xlin:href="file://MASTER/Prandtl_4.pdf" xmlns:xlin="http://www.w3.org/1999/xlink"/&gt;

所以我们删除/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams,而不是添加file://

这是我的 XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcterms="http://purl.org/dc/terms/">

<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" />

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


 <xsl:for-each select="/mets:mets/mets:filesec/mets:fileGrp/mets:file/mets:Flocat"> 
    <xsl:value-of select="xlin:href"/>
</xsl:for-each> 
    </xsl:template>

</xsl:stylesheet>

我对 XSLT 非常陌生,我不知道如何引用我必须更改的行。也许有一些想法?

【问题讨论】:

  • 如果您想更改属性值,请为该属性编写模板并实施该更改。你真的被限制在 XSLT version="1.0" 或者你为什么在你的 XSLT 代码中使用那个版本?

标签: xml xslt replace substitution


【解决方案1】:

考虑使用 XSLT 3(由 Saxon 9.8 或 Altova XMLSpy 2017 或 2018 支持),然后就很简单了

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mets="http://www.loc.gov/METS/"
    xmlns:xlin="http://www.w3.org/1999/xlink"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="mets:FLocat/@xlin:href">
      <xsl:attribute name="{name()}" select="'file://' || replace(., '^/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams', '')"/>
  </xsl:template>

</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/nbUY4kn

对于 XSLT 2,您需要将身份转换拼写为

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mets="http://www.loc.gov/METS/"
    xmlns:xlin="http://www.w3.org/1999/xlink"
    exclude-result-prefixes="#all"
    version="2.0">

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

  <xsl:template match="mets:FLocat/@xlin:href">
      <xsl:attribute name="{name()}" select="concat('file://', replace(., '^/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams', ''))"/>
  </xsl:template>

</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/nbUY4kn/2

使用 XSLT 1 没有一般的字符串替换,但是您可以在某个字符串之后使用属性值的结尾

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:mets="http://www.loc.gov/METS/"
    xmlns:xlin="http://www.w3.org/1999/xlink"
    exclude-result-prefixes="xs mets xlin"
    version="1.0">

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

  <xsl:template match="mets:FLocat/@xlin:href">
      <xsl:attribute name="{name()}">
          <xsl:value-of select="concat('file://', substring-after(., '/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV631313192/content/streams'))"/>
      </xsl:attribute>
  </xsl:template>

</xsl:stylesheet>

http://xsltfiddle.liberty-development.net/nbUY4kn/3

【讨论】:

  • 我忘了解释的是,可能会出现不同的数字而不是 GBV631313192,并且数字的数量并不总是恒定的。所以也许那里应该是正则表达式
  • 好吧,XSLT 2 和 3 解决方案已经使用带有 replace 函数 w3.org/TR/xpath-functions/#func-replace 的正则表达式,因此请根据您的需要进行调整,例如replace(., '^/exlibris1/transfer/lza-tib/submission.tib/ingest/GBV[0-9]+/content/streams', '')。纯 XSLT/XPath 1 不支持正则表达式,因此您首先需要确定您选择的 XSLT 处理器是否支持某些扩展功能或扩展机制(例如调用 Java、Javascript 或 .NET)才能使用正则表达式。
  • 在xslt 1.0中是否可以通过.*等通配符替换GBV631313192?
  • 不,不是在纯 XSLT/XPath 1.0 中。顺便说一句,你可以在w3.org/TR/xpath 找到它的功能。 xsltproc 可能支持扩展,请查看其文档。
猜你喜欢
  • 1970-01-01
  • 2013-06-29
  • 2011-02-05
  • 1970-01-01
  • 2013-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-29
相关资源
最近更新 更多