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() > 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() > 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('"', ., '"')'/>
</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('"', ., '"')'/>
</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
我想在 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() > 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() > 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('"', ., '"')'/>
</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('"', ., '"')'/>
</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