Пример массива и карты для xslt 3.0 и xpath3.1
Я хочу использовать новую функцию в XPath3.1, как array
а также map
, Это может звучать как вопрос googleable, но я пытаюсь многие примеры кода по-прежнему получают сообщение об ошибке, вот как я дошел до сих пор:
<!-- XSLT.xslt -->
<!-- using SaxonHE9-8-0-7 -->
<xsl:stylesheet version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" indent="yes"/>
<xsl:template match="/">
<xsl:copy-of select="system-property('xsl:version ')"/> <!-- show 3.0 -->
<xsl:copy-of select="system-property('xsl:vendor ')"/> <!-- show Saxonica -->
<xsl:copy-of select="system-property('xsl:xpath-version')"/> <!-- show 3.1 -->
<xsl:copy-of select="system-property('xsl:xsd-version ')"/> <!-- show 1.1 -->
</xsl:template>
</xsl:stylesheet>
Так что это простой и рабочий код, который может продемонстрировать силу array
а также map
? Спасибо!
1 ответ
Карты могут помочь в первую очередь с двумя проблемами:
- для этого смотрите https://www.w3.org/TR/xslt-30/, хотя при использовании Saxon 9.8 HE вы не можете использовать потоковую передачу.
- Обработка JSON, поскольку объекты JSON могут быть сопоставлены с XSLT 3 и соответственно картами XPath 3.1, см. https://www.w3.org/TR/xpath-functions/ и https://www.w3.org/TR/xslt-30/
Что касается простых примеров, различные разделы в спецификациях на карте и синтаксисе массива и функциях имеют простые примеры: чтобы использовать функции с XSLT, вам нужно только убедиться, что вы объявили пространства имен, в которых функции определены, например:
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
Я не уверен, что простые примеры могут продемонстрировать мощь новой языковой функции, а карты и массивы имеют различные функции, чтобы дать вам один пример, который преобразует некоторые входные данные XML в JSON путем создания карт (в одном шаблоне с использованием XSLT xsl:map
и в другом синтаксис конструктора карты XPath) и массивов и сериализации результата как json
:
<?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"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<xsl:output method="json" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="root">
<xsl:map>
<xsl:map-entry key="local-name()">
<xsl:apply-templates/>
</xsl:map-entry>
</xsl:map>
</xsl:template>
<xsl:template match="items">
<xsl:variable name="items" as="item()*">
<xsl:apply-templates/>
</xsl:variable>
<xsl:sequence select="map { local-name() : array { $items }}"/>
</xsl:template>
<xsl:template match="item">
<xsl:sequence select="map { 'foo' : xs:integer(foo), 'bar' : string(bar) }"/>
</xsl:template>
</xsl:stylesheet>
Так что преобразует
<root>
<items>
<item>
<foo>1</foo>
<bar>a</bar>
</item>
<item>
<foo>2</foo>
<bar>b</bar>
</item>
</items>
</root>
в JSON
{
"root": {
"items": [
{
"foo":1,
"bar":"a"
},
{
"foo":2,
"bar":"b"
}
]
}
}
Онлайн на http://xsltfiddle.liberty-development.net/b4GWV3.
Я также собрал другой пример на http://xsltfiddle.liberty-development.net/6qM2e27 который показывает несколько способов построения карт:
<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"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<xsl:output method="adaptive" indent="yes"/>
<!-- a map constructed with XPath 3.1 map constructor https://www.w3.org/TR/xpath-31/#id-map-constructors -->
<xsl:param name="map1" as="map(*)" select="map { 'string' : 'foo', 'number' : 3.14, 'boolean' : true(), 'sequence' : (1, 2, 3) }"/>
<xsl:param name="json-string" as="xs:string">
{
"foo" : "value 1",
"bar" : 3.14,
"baz" : true,
"items" : ["a", "b", "c" ]
}
</xsl:param>
<!-- a map constructed from a string containing JSON using the parse-json function https://www.w3.org/TR/xpath-functions/#func-parse-json -->
<xsl:param name="map2" as="map(*)" select="parse-json($json-string)"/>
<!-- a map constructed using the XSLT xsl:map and xsl:map-entry instructions https://www.w3.org/TR/xslt-30/#map-instructions -->
<xsl:param name="map3" as="map(*)">
<xsl:map>
<xsl:map-entry key="'key1'" select="'value 1'"/>
<xsl:map-entry key="'x'" select="3.1415927"/>
</xsl:map>
</xsl:param>
<!-- a map constructed by merging several maps using the map:merge function https://www.w3.org/TR/xpath-functions/#func-map-merge -->
<xsl:param name="map4" as="map(*)" select="map:merge(($map1, $map2, $map3))"/>
<!-- a map constructed by putting a new value into an existing map using the map:put function https://www.w3.org/TR/xpath-functions/#func-map-put -->
<xsl:param name="map5" as="map(*)" select="map:put($map1, 'new-key', 'new value')"/>
<xsl:template match="/">
<xsl:sequence select="$map1, $map2, $map3, $map4, $map5"/>
</xsl:template>
</xsl:stylesheet>
Вывод этого таков (к сожалению, в настоящее время в Saxon нет способа красиво распечатать / сделать отступы с помощью метода вывода "adaptive"):
map{"sequence":(1,2,3),"boolean":true(),"number":3.14,"string":"foo"}
map{"items":["a","b","c"],"foo":"value 1","bar":3.14e0,"baz":true()}
map{"key1":"value 1","x":3.1415927}
map{"items":["a","b","c"],"sequence":(1,2,3),"foo":"value 1","boolean":true(),"number":3.14,"string":"foo","key1":"value 1","bar":3.14e0,"x":3.1415927,"baz":true()}
map{"sequence":(1,2,3),"boolean":true(),"number":3.14,"string":"foo","new-key":"new value"}
И похожий пример, показывающий некоторые основные варианты построения массивов:
<?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"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<xsl:output method="adaptive" indent="yes"/>
<!-- array created with square array constructor https://www.w3.org/TR/xpath-31/#prod-xpath31-SquareArrayConstructor -->
<xsl:param name="array1" as="array(xs:integer)" select="[1, 2, 3, 4]"/>
<!-- array created with curly braces array constructor https://www.w3.org/TR/xpath-31/#prod-xpath31-CurlyArrayConstructor -->
<xsl:param name="array2" as="array(xs:string)" select="array{ (string-to-codepoints('A') to string-to-codepoints('E'))!codepoints-to-string(.) }"/>
<!-- if we use the square array constructor with an expression like above inside we get an array containing a sequence of strings -->
<xsl:param name="array3" as="array(xs:string*)" select="[ (string-to-codepoints('A') to string-to-codepoints('E'))!codepoints-to-string(.) ]"/>
<xsl:param name="json-array-as-string" as="xs:string">
[ { "foo" : 1 }, { "foo" : 2 }, { "foo" : 3 } ]
</xsl:param>
<!-- array constructed by parsing JSON input with function parse-json https://www.w3.org/TR/xpath-functions/#func-parse-json -->
<xsl:param name="array4" as="array(map(xs:string, xs:double))" select="parse-json($json-array-as-string)"/>
<!-- array constructed by joining two arrays using the function array:join https://www.w3.org/TR/xpath-functions/#func-array-join -->
<xsl:param name="array5" as="array(*)" select="array:join(($array1, $array2))"/>
<!-- array constructed by extracting subarray with function array:subarray https://www.w3.org/TR/xpath-functions/#func-array-subarray -->
<xsl:param name="array6" as="array(*)" select="array:subarray($array5, 3, 4)"/>
<xsl:template match="/">
<xsl:sequence select="$array1, $array2, $array3, $array4, $array5, $array6"/>
</xsl:template>
</xsl:stylesheet>
какие выводы
[1,2,3,4]
["A","B","C","D","E"]
[("A","B","C","D","E")]
[map{"foo":1.0e0},map{"foo":2.0e0},map{"foo":3.0e0}]
[1,2,3,4,"A","B","C","D","E"]
[3,4,"A","B"]
http://xsltfiddle.liberty-development.net/eiQZDbd
На этом этапе публикации может также стоить рассмотреть различные тестовые случаи в XSLT 3 и комбинированные тестовые наборы XPath и XQuery, например:
- https://dvcs.w3.org/hg/xslt30-test/file/tip/tests/strm/si-map использует
xsl:map
с потоковым - https://dvcs.w3.org/hg/xslt30-test/file/tip/tests/fn/xml-to-json имеет тесты для
xml-to-json
- https://dvcs.w3.org/hg/xslt30-test/file/tip/tests/fn/json-to-xml имеет
json-to-xml
контрольные примеры.