Xpath 'instance of' 在 solr xslt 中不工作

Xpath 'instance of' not working in solr xslt

我想在 solr 中使用 xslt 在 json 中输出没有特定 solr 属性的结果。

    {
      "techproducts": [
         {
            "id": "GB18030TEST",
            "price": "0.0"
         },
         {
            "id": "SOLR1000",
            "price": "0.0"
         },
         {
            "id": "UTF8TEST",
            "price": "0.0"
         }
      ],
      "paging": {
        "count": 3
      }
    }

字段类型(数字或布尔值)的测试test=". instance of xs:integer"为了添加或不添加引号不起作用并生成 500 错误。

http://localhost:8090/solr/techproducts/select?q=*&fq=price:0&fl=id,price&wt=xslt&tr=json_paginate.xsl

 Caused by: javax.xml.transform.TransformerConfigurationException: solrres:/xslt/json_paginate.xsl: line 37: Attribut 'test' obligatoire manquant.

有什么建议吗?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" >

  <xsl:strip-space elements="*"/>
  <xsl:output method="text" indent="no" media-type="application/json"/>

    <xsl:template match='/'>
        <xsl:text>{"techproducts":[</xsl:text>
        <xsl:apply-templates select="response/result/doc"/>
        <xsl:text>],</xsl:text>
        <xsl:text>"paging":{"count":</xsl:text><xsl:value-of select="response/result/@numFound"/><xsl:text>}}</xsl:text>
    </xsl:template> 

  <xsl:template match="doc"> 
    <xsl:variable name="pos" select="position()"/>
    <xsl:if test="position() &gt; 1">
        <xsl:text>,</xsl:text>
       </xsl:if>

    <xsl:text>{</xsl:text>
        <xsl:apply-templates>
            <xsl:with-param name="pos"><xsl:value-of select="$pos"/></xsl:with-param>
        </xsl:apply-templates>
    <xsl:text>}</xsl:text>
  </xsl:template>

  <xsl:template match="doc/*">
    <xsl:if test="position() &gt; 1">
        <xsl:text>,</xsl:text>
       </xsl:if>
    <xsl:text>"</xsl:text><xsl:value-of select="@name"/><xsl:text>":</xsl:text>

    <xsl:choose>
        <!-- if integer, do not add quotes -->
        <xsl:when test=". instance of xs:integer">
            <xsl:value-of select="."/>
        </xsl:when>
        <!-- if boolean, do not add quotes -->
        <xsl:when test=". instance of xs:boolean">
            <xsl:value-of select="."/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>"</xsl:text><xsl:value-of select="."/><xsl:text>"</xsl:text>          
        </xsl:otherwise>
    </xsl:choose>

  </xsl:template>
</xsl:stylesheet>

解决问题: 我已经在 solr http://wiki.apache.org/solr/XsltResponseWriter 中升级了 xslt 版本并使用了

<xsl:choose>
    <!-- if decimal, do not add quotes -->
    <xsl:when test=". castable as xs:decimal">
        <xsl:value-of select="."/>
    </xsl:when>
    <!-- if boolean, do not add quotes -->
    <xsl:when test=". castable as xs:boolean">
        <xsl:value-of select="."/>
    </xsl:when>
    <xsl:otherwise>
        <xsl:text>"</xsl:text><xsl:value-of select="."/><xsl:text>"</xsl:text>          
    </xsl:otherwise>
</xsl:choose>

您的目标是获得语法正确的 JSON 数据:数字和字符串 "true" 和 "false" 没有引号。这就是你处理这些数据类型的尝试告诉我的。

在这种情况下,以下 xsl:choose 部分应该有效 - 至少我希望如此,因为我们不知道您的输入数据:

XSLT-2.0: (*)

  <xsl:choose>
      <!-- if number, do not add quotes -->
      <xsl:when test="number(.)">
          <xsl:value-of select="."/>
      </xsl:when>
      <!-- if boolean, do not add quotes -->
      <xsl:when test="matches(.,'true|false','i')">
          <xsl:value-of select="lower-case(.)"/>
      </xsl:when>
      <xsl:otherwise>
          <xsl:text>"</xsl:text><xsl:value-of select="."/><xsl:text>"</xsl:text>          
      </xsl:otherwise>
  </xsl:choose>

应该提到(见评论)所有 数字 打印时都没有引号。不仅 整数 。对于有效的 JSON 输出应该没问题。

(*) 我的答案的第一个版本有很多错误,对此我深表歉意(否决该答案是非常合适的)。上面显示的版本已经过 Saxon 测试并按预期工作。

以下是如何在 XSLT 1.0 中实现所提供的 XSLT 2.0 代码的预期行为:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="text"/>

  <xsl:template match=
  "*[not(*) and text() 
  and 
    not(contains('|true|false|', concat('|', ., '|')))]">
   <xsl:value-of select='concat(&apos;&quot;&apos;, ., &apos;&quot;&apos;)'/>
 </xsl:template>

 <xsl:template match="*[not(*) and text() and number(.) = .]" priority="3">
   <xsl:value-of select="number(.)"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:

<t>
 <a>1</a>
 <b>true</b>
 <c>false</c>
 <d>-3</d>
 <e>x</e>
 <f>.25</f>
</t>

产生了想要的、正确的结果:

 1
 true
 false
 -3
 "x"
 0.25

请注意:除了提供的 XSLT 2.0 代码中预期的行为外,上述转换还实现了 JSON 的正确输出 - 可接受的表示形式任何小数。

如果只需要处理和显示整数值,只需使用:

floor(.) = .

更新:

OP 刚刚透露他实际上可以使用 XSLT 2.0 处理器。

这是一种可能的 XSLT 2.0 解决方案,它正确地将字符串 "true""false" 表示为 JSON 布尔值,任何整数和小数到 JSON 数字,以及任何其他原子值——引用字符串:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xs="http://www.w3.org/2001/XMLSchema">
 <xsl:output method="text"/>

  <xsl:template match=
  "*[not(*) and text() and not(. = ('true', 'false'))]">
   <xsl:value-of select='concat(&apos;&quot;&apos;, ., &apos;&quot;&apos;)'/>
 </xsl:template>

 <xsl:template match="*[not(*) and text() and . castable as xs:decimal]" priority="3">
   <xsl:value-of select="number(.)"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档时(如上图,产生了相同的正确、想要的结果:

 1
 true
 false
 -3
 "x"
 0.25