【问题标题】:XSLT Copy, Trim, Sort and Delete in one transformXSLT 在一次转换中复制、修剪、排序和删除
【发布时间】:2017-02-01 13:51:46
【问题描述】:

我有以下 XML。

<oai_dc:dc xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/">
    <dc:title xmlns:dc="http://purl.org/dc/elements/1.1/" xml:lang="hrv">Naslov rada</dc:title>
    <dc:date xmlns:dc="http://purl.org/dc/elements/1.1/">2001-01-01</dc:date>
    <dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Prezime, Ime</dc:creator>
    <dc:date xmlns:dc="http://purl.org/dc/elements/1.1/">2002-02-02</dc:date>
    <dc:relation xml:lang="eng">University of Zagreb. Academy of dramatic art. </dc:relation>
</oai_dc:dc>

我需要的输出是这样的:

<dc>
    <creator>Prezime, Ime</creator>
    <date>2002-02-02</date> 
    <relation lang="eng">University of Zagreb. Academy of dramatic art.</relation>
    <title lang="hrv">Naslov rada</title>   
</dc>

所以,我需要做的是:从属性和元素中删除命名空间。我用这段代码试过了,它可以工作。

<xsl:template match="*">
 <xsl:element name="{local-name()}">
  <xsl:apply-templates select="@*|node()"/>
 </xsl:element>
</xsl:template>
<xsl:template match="@*">
 <xsl:attribute name="{local-name()}">
  <xsl:value-of select="."/>
 </xsl:attribute>
</xsl:template>

接下来我需要按元素名称(也可能按属性名称)对元素进行排序。我用这段代码做到了,它可以工作。

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

然后我需要删除所有以“2001”开头的元素。我就是这样做的,它可以工作。

<xsl:template match="/dc/date[starts-with(text(), '2001')]" />

最后,我必须修剪元素中的所有文本值。注意:

<dc:relation xml:lang="eng">University of Zagreb. Academy of dramatic art. </dc:relation>

我应该从结尾(和开头)修剪空白,所以它是:

<dc:relation xml:lang="eng">University of Zagreb. Academy of dramatic art.</dc:relation>

所以我的问题是我不能让它在一个 XSLT 组合中工作。想法是:从定义命名空间的元素和属性中删除前缀(命名空间),然后对元素进行排序并删除一些特定元素(如我的情况),最后修剪所有剩余的文本值。

我做了这一切,但有不止一个变换。是否可以一口气完成?

我只能使用 XSLT 1.0

【问题讨论】:

  • 您不想删除xml:lang 属性上的xml: 前缀,任何带有xml: 前缀的属性在XML 中都有特殊含义。此外,小点但您输入的 XML 无效,它缺少 dc:relation 元素上的 xmlns:dc 声明。很明显它应该是什么,但它应该使任何这样的 XML 解析器失败。
  • 是的,该关系元素应该为有效的 xml 声明 dc。 Tnx 通知!

标签: xml sorting xslt namespaces trim


【解决方案1】:

使用

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
  xmlns:oai_dc="http://www.openarchives.org/OAI/2.0/oai_dc/"
  xmlns:dc="http://purl.org/dc/elements/1.1/">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

<xsl:template match="*">
 <xsl:element name="{local-name()}">
  <xsl:apply-templates select="@*">
      <xsl:sort select="local-name()"/>
  </xsl:apply-templates>
  <xsl:apply-templates select="node()">
      <xsl:sort select="local-name()"/>
  </xsl:apply-templates>
 </xsl:element>
</xsl:template>

<xsl:template match="@*">
 <xsl:attribute name="{local-name()}">
  <xsl:value-of select="."/>
 </xsl:attribute>
</xsl:template>

<xsl:template match="/oai_dc:dc/dc:date[starts-with(text(), '2001')]" />

<xsl:template match="text()[normalize-space()]">
    <xsl:value-of select="normalize-space()"/>
</xsl:template>

</xsl:transform>

创建输出 (http://xsltransform.net/3NSSEvB)

<dc>
   <creator>Prezime, Ime</creator>
   <date>2002-02-02</date>
   <relation lang="eng">University of Zagreb. Academy of dramatic art.</relation>
   <title lang="hrv">Naslov rada</title>
</dc>

请注意,normalize-space() 的使用不仅会修剪前导和尾随空白,还会将其他字符之间的任何空白序列替换为单个空格。

【讨论】:

  • 次要问题,但 xml:lang 不应删除前缀。我知道这是 OP 要求的,但我相信您知道,xml: 属性具有特殊含义。
  • @Flynn1179,我理解你的担心,但命名空间也有含义,所以我认为如果有人想要剥离命名空间,那么剥离预定义的 xml: 前缀是在指定的任务范围内。
  • 是的,xml: 和 xmlns: 之间是有区别的,但此时我的目标是将 2 个 xmls 减少到最小,以便进行简单的比较(字符串比较),而不需要遍历每个节点和属性。这个解决方案对我来说很漂亮!泰!
猜你喜欢
  • 2018-05-01
  • 2012-02-19
  • 1970-01-01
  • 2016-04-07
  • 1970-01-01
  • 2012-07-21
  • 1970-01-01
  • 2014-09-17
  • 1970-01-01
相关资源
最近更新 更多