首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在JDom XSL转换中不工作的(@属性)测试?

在JDom XSL转换中不工作的(@属性)测试?
EN

Stack Overflow用户
提问于 2015-08-25 20:39:32
回答 2查看 434关注 0票数 1

我有一个XSLT样式表,它使用xsltproc按预期工作,但在实际应用程序中生成一个不同的输出,其中转换通过org.jdom.transform.XSLTransformer (jdom 1.0)应用,我相信使用Xalan。

样式表片段(这是更大的模板的一部分,开头如下:<xsl:template match="/dspace:dim[@dspaceType='ITEM']">):

代码语言:javascript
复制
<xsl:if test="//dspace:field[@mdschema='dc' and @element='rights']">
  <rightsList>
    <xsl:if test="//dspace:field[@mdschema='dc' and @element='rights' and not(@qualifier) and @language='*']">
      <rights>
        <xsl:if test="//dspace:field[@mdschema='dc' and @element='rights' and @qualifier='uri' and @language='*']">
          <xsl:attribute name="rightsUri">
            <xsl:value-of select="//dspace:field[@mdschema='dc' and @element='rights' and @qualifier='uri' and @language='*']"/>
          </xsl:attribute>
        </xsl:if>
        <xsl:value-of select="//dspace:field[@mdschema='dc' and @element='rights' and not(@qualifier) and @language='*']" />
      </rights>
    </xsl:if>
    <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='rights' and not(@language='*')]" />
  </rightsList>
</xsl:if>

代码语言:javascript
复制
<xsl:template match="//dspace:field[@mdschema='dc' and @element='rights' and not(@language='*')]">
    <rights><xsl:value-of select="." /></rights>
</xsl:template>

XML片段:

代码语言:javascript
复制
<dim:dim dspaceType="ITEM" xmlns:dim="http://www.dspace.org/xmlns/dspace/dim">
  <dim:field element="rights" language="en_NZ" mdschema="dc">Actual text redacted</dim:field>
  <dim:field element="rights" language="*" mdschema="dc">Attribution 3.0 New Zealand</dim:field>
  <dim:field element="rights" qualifier="uri" language="*" mdschema="dc">http://creativecommons.org/licenses/by/3.0/nz/</dim:field>
</dim:dim>

使用xsltproc,这会产生

代码语言:javascript
复制
<rightsList>
  <rights rightsUri="http://creativecommons.org/licenses/by/3.0/nz/">Attribution 3.0 New Zealand</rights>
  <rights>Actual text redacted</rights>
</rightsList>

在我的应用程序中,这会产生

代码语言:javascript
复制
<rightsList>
  <rights>Actual text redacted</rights>
  <rights>Attribution 3.0 New Zealand</rights>
  <rights>http://creativecommons.org/licenses/by/3.0/nz/</rights>
</rightsList>

因此,在我看来,使用jdom时,not(@qualifier)位似乎无法工作。

我希望了解一下这里发生了什么,以及如何更改样式表,以在我的应用程序中获得与目前通过xsltproc获得的相同结果。

编辑以添加:为了防止有任何不同,样式表从

代码语言:javascript
复制
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
            xmlns:dspace="http://www.dspace.org/xmlns/dspace/dim"
            xmlns:exslt="http://exslt.org/common"
            xmlns="http://datacite.org/schema/kernel-3"
            extension-element-prefixes="exslt"
            exclude-result-prefixes="exslt"
            version="1.0">

还包括此模板:

代码语言:javascript
复制
<!-- Don't copy everything by default! -->
<xsl:template match="@* | text()" />

看到了我在下面的答案-- XML实际上与我想象的不同,所以问题并不在XSL中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-08-25 23:56:34

除了解决原来的问题之外,让我们快速了解一下如何重新组织代码。

您使用了很多//foo表达式。使用//foo启动表达式意味着“在任何级别上搜索整个文档,以查找名称为foo的元素”。除了这是一个潜在的昂贵操作,这通常会产生不必要的副作用,并使您的代码难以阅读,因为它要求您唯一地指定每个元素,从而导致大量重复的代码。

您也使用了大量的xsl:if,但是在XSLT中,几乎没有必要使用if-语句(XSLT1.0和2.0中的一个例外是在处理节点以外的事情时)。在几乎所有的情况下,您都可以用简单的xsl:if替换xsl:apply-templates

尽管如此,让我们看看如何重写您的代码以获得相同的效果,并且减少出错的机会:

代码语言:javascript
复制
<xsl:if test="//dspace:field[@mdschema='dc' and @element='rights']">
    <rightsList>
      .....

类似于有一个匹配的模板,如下所示(假设您有一个用于无趣节点的丢弃模板):

代码语言:javascript
复制
<xsl:template match="dspace:dim[dspace:field[@mdschema='dc' and @element='rights']]">
    <rightsList>

这说明:如果遇到具有这些属性集的任何dim元素,则输出<rightsList>

那你就有:

代码语言:javascript
复制
<xsl:if test="//dspace:field[@mdschema='dc' and @element='rights' and not(@qualifier) and @language='*']">
    <rights>

它与以下应用模板表达式(假设与其匹配的模板)完全等价:

代码语言:javascript
复制
<xsl:apply-templates select="dspace:field[@mdschema='dc' and @element='rights' and not(@qualifier) and @language='*']" />

在这里,我们发现在这个下面,我们有一个几乎等价的表达式,这次是关于not(@language='*')的。那么,让我们看看我们是否能完全消除那些重复的表达式。

首先,让我们回顾一下,看看您在做什么:

  • 如果任何地方有"dc“和”权限“,则创建一个<rightsList>
  • 如果其中任何一个都没有限定符,而是有语言"*",则创建<rights>
  • 在其中,如果任何限定符都有值"uri“和"*",则创建一个属性rightsUri,将其值设置为找到的第一个
  • 在这个<rights>元素(在当前结构中最多可以有一个)之后,为每个字段元素创建一个带有语言"*“的<rights>列表。

如果这是正确的,那么可以重写如下:

代码语言:javascript
复制
<xsl:template match="dspace:dim[dspace:field[@mdschema='dc' and @element='rights']]">
    <xsl:variable name="adjusted">
        <xsl:copy-of select="dspace:field[@mdschema='dc' and @element='rights']"/>
    </xsl:variable>

    <rightsList>
        <xsl:apply-templates select="exsl:node-set($adjusted)/*[not(@qualifier) and @language='*'][1]" mode="noquali"/>
        <xsl:apply-templates select="exsl:node-set($adjusted)/*[not(@language='*')]" />
    </rightsList>
</xsl:template>

<xsl:template match="dspace:field" mode="noquali">
    <rights>
        <xsl:apply-templates select="/dspace:field[@qualifier='uri' and @language='*'][1]" mode="uri"/>
        <xsl:value-of select="."/>
    </rights>
</xsl:template>

<xsl:template match="dspace:field" mode="uri">
    <xsl:attribute name="rightsUri" select="." />
</xsl:template>

<!-- matching anything else -->
<xsl:template match="dspace:field">
    <rights><xsl:value-of select="." /></rights>
</xsl:template>

几乎每个XSLT1.0处理器都支持exsl:node-set函数,只需将名称空间xmlns:exsl="http://exslt.org/common"添加到xsl:stylesheet声明中即可。

注意,我在select表达式中添加了几次[1]。虽然在代码中没有这样做,但当前代码具有相同的效果,但是如果使用apply-模板,如果遇到多个匹配,则必须指定只对第一个匹配感兴趣。

我认为您的代码可以进一步简化,但我希望确保逻辑保持不变。正如您所看到的,最终的结果是没有任何//。但是,您确实看到了一个/,它现在指向节点集的根,它很方便地只有您感兴趣的节点:那些具有模式"dc“和”right“元素属性的节点,因此我们不必一次又一次地重复该表达式。

您可以尝试这个重写,看看它是否对您当前的错误有帮助,否则我很乐意进一步帮助您。

编辑

编辑之后,原来的上下文项已经是dspace:dim了。如果您不介意总是输出<rightsList> (即使它是空的),您可以简单地用现有的dspace:dim模式替换上面的第一个模板匹配模式。

票数 2
EN

Stack Overflow用户

发布于 2015-08-26 04:16:46

是啊。的确是森林/树木。尽管语言属性在应用程序中的其他地方几乎都被称为" language“(请参见我给出的XML代码段),但在我的样式表所操作的XML中,它实际上被称为"lang”--我最终让步并使用这个答案来确定XML结构是什么。惊喜吧!

无论如何,我在一定程度上遵循了亚伯他的回答中给出的建议,并对这个特定情况的模板进行了相当程度的简化。我现在刚刚

代码语言:javascript
复制
<xsl:if test="dspace:field[@mdschema='dc' and @element='rights']">
    <rightsList>
        <xsl:apply-templates select="dspace:field[@mdschema='dc' and @element='rights']"/>
    </rightsList>
</xsl:if>

在大模板中,加上几个自定义模板:

代码语言:javascript
复制
<xsl:template match="dspace:field[@mdschema='dc' and @element='rights']">
    <xsl:choose>
        <xsl:when test="@qualifier='uri'"/>
        <xsl:otherwise>
            <rights>
                <xsl:if test="@lang='*'">
                    <xsl:apply-templates select="//dspace:field[@mdschema='dc' and @element='rights' and @qualifier='uri' and @lang='*'][1]" mode="rightsURI"/>
                </xsl:if>
                <xsl:value-of select="."/>
            </rights>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="dspace:field[@mdschema='dc' and @element='rights' and @qualifier='uri' and @lang='*']" mode="rightsURI">
    <xsl:attribute name="rightsURI"><xsl:value-of select="."/></xsl:attribute>
</xsl:template>
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/32213625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档