XSLT 3.0 迭代包裹在 XML 中的 JSON 数组
XSLT 3.0 iterate over JSON array wrapped in XML
我正在使用 XSLT 处理各种 XML 文件。在一个 XML 中,我找到了一个包装好的 JSON 列表:
<list><![CDATA[[
{
"title": "Title 1",
"value": "Value 1",
"order": 1
},
{
"title": "Title 2",
"value": "Value 2",
"order": 2
}
]]]>
</list>
我的问题是我需要遍历列表。例如:
<xsl:variable name="listVar">
<!-- do something with list -->
</xsl:variable>
<xsl:for-each select="$listVar">
<!-- do something with objects in list e.g. -->
<xsl:value-of select="title"/>
<xsl:value-of select="value"/>
</xsl:for-each>
如何使用 XSLT 执行此操作?我使用 XSLT 3.0 和 Saxon 引擎,版本 9.8 HE。
考虑过的解决方案:
1。
使用 parse-json
函数:
但是由于 XPathException:"Required item type of the context item for the child axis is node(); supplied value (.) has item type array(function(*))" 或 "Maps cannot be atomized",我无法迭代结果。我发现有
我可能应该考虑的功能,例如 map:get、map:entry,但到目前为止我没有在我的案例中使用它们。
2。
在上面提到的那个之前的附加变换:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="xml" encoding="UTF-8" indent="no"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="list">
<list>
<xsl:copy-of select="json-to-xml(.)"/>
</list>
</xsl:template>
</xsl:stylesheet>
然后:
<xsl:variable name="listVar" select="list/array/map"/>
但它不起作用 - 可能是由于添加了命名空间
<list>
<array xmlns="http://www.w3.org/2005/xpath-functions">
<map>
...
您的 JSON 结构在使用 parse-json
解析时在 XSLT/XPath 侧为您提供 array of maps and the most straightforward way to process the individual array items is with the ?*
lookup operator,然后您可以使用 for-each
甚至 apply-templates
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:template match="list">
<xsl:apply-templates select="parse-json(.)?*"/>
</xsl:template>
<xsl:template match=".[. instance of map(xs:string, item())]">
<xsl:value-of select="?title, ?value"/>
</xsl:template>
</xsl:stylesheet>
在何处访问地图值,您可以再次使用 ?foo
,如上所示。
至于处理由 json-to-xml
返回的 XML,它 returns XPath 函数命名空间中的元素因此 select 它们,与处理任何其他元素一样一个命名空间,你需要确保你设置了一个命名空间,例如xpath-default-namespace
对于您要处理来自该命名空间的元素的部分,或者您可以使用命名空间通配符,例如*:array/*:map
.
我正在使用 XSLT 处理各种 XML 文件。在一个 XML 中,我找到了一个包装好的 JSON 列表:
<list><![CDATA[[
{
"title": "Title 1",
"value": "Value 1",
"order": 1
},
{
"title": "Title 2",
"value": "Value 2",
"order": 2
}
]]]>
</list>
我的问题是我需要遍历列表。例如:
<xsl:variable name="listVar">
<!-- do something with list -->
</xsl:variable>
<xsl:for-each select="$listVar">
<!-- do something with objects in list e.g. -->
<xsl:value-of select="title"/>
<xsl:value-of select="value"/>
</xsl:for-each>
如何使用 XSLT 执行此操作?我使用 XSLT 3.0 和 Saxon 引擎,版本 9.8 HE。
考虑过的解决方案:
1。
使用 parse-json
函数:
但是由于 XPathException:"Required item type of the context item for the child axis is node(); supplied value (.) has item type array(function(*))" 或 "Maps cannot be atomized",我无法迭代结果。我发现有 我可能应该考虑的功能,例如 map:get、map:entry,但到目前为止我没有在我的案例中使用它们。
2。 在上面提到的那个之前的附加变换:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="xml" encoding="UTF-8" indent="no"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="list">
<list>
<xsl:copy-of select="json-to-xml(.)"/>
</list>
</xsl:template>
</xsl:stylesheet>
然后:
<xsl:variable name="listVar" select="list/array/map"/>
但它不起作用 - 可能是由于添加了命名空间
<list>
<array xmlns="http://www.w3.org/2005/xpath-functions">
<map>
...
您的 JSON 结构在使用 parse-json
解析时在 XSLT/XPath 侧为您提供 array of maps and the most straightforward way to process the individual array items is with the ?*
lookup operator,然后您可以使用 for-each
甚至 apply-templates
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
exclude-result-prefixes="xs math"
version="3.0">
<xsl:template match="list">
<xsl:apply-templates select="parse-json(.)?*"/>
</xsl:template>
<xsl:template match=".[. instance of map(xs:string, item())]">
<xsl:value-of select="?title, ?value"/>
</xsl:template>
</xsl:stylesheet>
在何处访问地图值,您可以再次使用 ?foo
,如上所示。
至于处理由 json-to-xml
返回的 XML,它 returns XPath 函数命名空间中的元素因此 select 它们,与处理任何其他元素一样一个命名空间,你需要确保你设置了一个命名空间,例如xpath-default-namespace
对于您要处理来自该命名空间的元素的部分,或者您可以使用命名空间通配符,例如*:array/*:map
.