XSLT 3 Saxon,使用深度更新和过滤器过滤不需要的数组元素
XSLT 3 Saxon, filtering unwanted array elements using deep-update and filter
XSLT 3 在使用 Saxon EE 库功能('saxon:with-pedigree'、'saxon:pedigree(.)?容器和 'deep-update')。下面的 XSLT 将具有 'visibility' 属性值的数组对象标识为 'false',然后从父数组对象中排除所选对象。跟踪显示预期值,但 Saxon Deep 更新操作逻辑失败。标识和数组过滤按预期工作,但将过滤后的数组分配给属性未按预期工作,感谢您的意见。
JSON嵌入在XML
<list><![CDATA[
{
"customers":[
{
"customerType": "householdCustomer",
"firstName": "Adam",
"lastName": "L",
"orders": [
{
"type": "smallOrder",
"refUri": "orders/smallorder/xyz",
"total": 125.0,
"shippingAddUri": "/customer/123/address/89ui",
"messages": [
{
"visibility": true,
"description": " your ordered delivered",
"id": "2345"
},
{
"visibility": false,
"description": "supplier challenge - covid supply chain issues",
"id": "2167"
},
{
"visibility": false,
"description": "order routed to correct procurement",
"id": "2049"
},
{
"visibility": false,
"description": "order gone to wrong procurement center",
"id": "2047"
},
{
"visibility": true,
"description": "order initiated",
"id": "2045"
}
]
},
{
"type": "smallOrder",
"refUri": "orders/smallorder/567z",
"total": 135.0,
"shippingAddUri": "/customer/678/address/90ny",
"messages": [
{
"id": "23456",
"visibility": true,
"description": " your ordered delayed"
},
{
"id": "21677",
"visibility": false,
"description": "internal costcenter labor strike "
},
{
"id": "20459",
"visibility": true,
"description": "order initiated"
}
]
}
]
},
{
"customerType": "householdCustomer",
"firstName": "Thomas",
"lastName": "N",
"orders": [
{
"type": "smallOrder",
"refUri": "orders/smallorder/xyz",
"total": 125.0,
"shippingAddUri": "/customer/123/address/89ui",
"messages": [
{
"id": "2345",
"visibility": true,
"description": " your ordered delivered"
},
{
"id": "2167",
"visibility": false,
"description": "supplier challenge - covid supply chain issues"
},
{
"id": "2045",
"visibility": false,
"description": "order initiated"
}
]
},
{
"type": "smallOrder",
"refUri": "orders/smallorder/xr7z",
"total": 234.0,
"shippingAddUri": "/customer/uio/address/34bnmy",
"messages": [
{
"id": "90",
"visibility": true,
"description": " your ordered delayed"
},
{
"id": "67",
"visibility": false,
"description": "Postal delays, finding alternative route "
},
{
"id": "34",
"visibility": true,
"description": "order initiated"
}
]
}
]
},
{
"customerType": "corporateCustomer",
"corpName": "Telsoft Inc",
"orders": [
{},
{}
]
},
{
"customerType": "corporateCustomer",
"corpName": "Orange Inc",
"orders": [
{},
{}
]
},
{
"customerType": "corporateCustomer",
"corpName": "Notebook Inc",
"orders": [
{},
{}
]
}
]
}
]]>
</list>
XSLT 以本地方式转换 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:fn="http://www.w3.org/2005/xpath-functions" xmlns:saxon="http://saxon.sf.net/" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:f="http://example.com/f" extension-element-prefixes="saxon" exclude-result-prefixes="array fn map math xhtml xs err saxon" version="3.0">
<xsl:output method="text" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="list" name="xsl:initial-template">
<!-- read json from XML -->
<xsl:variable name="data" as="map(*)" select="parse-json(.)"/>
<!-- identify household customers -->
<xsl:variable name="householdCustomers" as="array(*)">
<saxon:array select="$data?customers?*[?customerType='householdCustomer']"/>
</xsl:variable>
<!-- produce hhsWithPedigree refrence structure using WithPedigree -->
<xsl:variable name="hhsWithPedigree" as="array(*)">
<saxon:array select="$householdCustomers => saxon:with-pedigree()"/>
</xsl:variable>
<!-- identify all objects with visibility as false' -->
<xsl:variable name="visibilityArrayWithFalse" as="array(*)">
<saxon:array select="saxon:map-search($hhsWithPedigree, 'visibility', function($v){ fn:matches(
xs:string($v), 'false') })"/>
</xsl:variable>
<!-- iterate through objects with 'visibility' attribute value as 'false' then identify root array
and exclude the selected objects -->
<xsl:for-each select="$visibilityArrayWithFalse?*?map">
<xsl:variable name="visiOne" select="saxon:pedigree(.)?container"/>
<saxon:deep-update
root = "$visiOne"
select = "."
action = " let $filteredValues := array:filter(., function($v) {map:get($v,'visibility') eq true() }), $noOfValues := count($filteredValues), $trace := trace($filteredValues, 'I m tracing') return $filteredValues "/>
</xsl:for-each>
<xsl:value-of select=" $householdCustomers => serialize(map { 'method' : 'json', 'use-character-maps' : map { '/' : '/' } })"/>
</xsl:template>
</xsl:stylesheet>
错误详细信息:
Error in saxon:deep-update/@root on line 31 column 222 of question-v1.xslt:
SENR0001: Cannot serialize a map using this output method
Focus
Context item: map{"visibility":false(), "description":"supplier challenge - covid supply c...", "id":"2167", }
Context position: 1
Local variables
$vv:v0 = coerced anon:f_1766145591
$householdCustomers = [map{"firstName":"Adam", "lastName":"L", "customerType":"householdCustomer", ...}, map{"firstName":"Thomas", "lastName":"N", "customerType":"householdCustomer", ...}, ]
invoked by unknown caller (class net.sf.saxon.expr.instruct.ForEach) at file:/C:/apps/xslt3/question-v1.xslt#26
In template rule with match="list" on line 6 of question-v1.xslt
Focus
Context item: /list
Context position: 1
Local variables
$vv:v0 = coerced anon:f_1766145591
$householdCustomers = [map{"firstName":"Adam", "lastName":"L", "customerType":"householdCustomer", ...}, map{"firstName":"Thomas", "lastName":"N", "customerType":"householdCustomer", ...}, ]
invoked by built-in template rule (text-only)
Cannot serialize a map using this output method
我认为部分错误是你使用了saxon:deep-update
而没有将其结果存储在一个可以带XDM映射或数组的变量中,即指令returns/outputs这样的映射或数组在里面xsl:for-each
的输出方法为 text
,您会收到错误消息,因为 saxon:deep-update
返回的结果序列化无法使用该方法 text
进行序列化。
我不太确定你想要实现什么,但我猜你不想输出 saxon:deep-update
的结果,你只希望它在你的地图上产生副作用。
阅读更多关于 saxon:deep-update
的内容,我想知道您是否需要所有明确的血统使用,以下
<xsl:template match="list" name="xsl:initial-template">
<!-- read json from XML -->
<xsl:variable name="data" as="map(*)" select="parse-json(.)"/>
<!-- identify household customers -->
<xsl:variable name="householdCustomers" select="array { $data?customers?*[?customerType='householdCustomer']}"/>
<xsl:variable name="update-result" as="item()*">
<saxon:deep-update root="$householdCustomers"
select="?*?orders?*?messages"
action="array:filter(., function($v) { $v?visibility })"/>
</xsl:variable>
<xsl:value-of select=" $update-result => serialize(map { 'method' : 'json', 'indent' : true(), 'use-character-maps' : map { '/' : '/' } })"/>
</xsl:template>
产出
[
{
"lastName": "L",
"orders": [
{
"total": 125,
"messages": [
{ "visibility": true,"description": " your ordered delivered","id": "2345" },
{ "visibility": true,"description": "order initiated","id": "2045" }
],
"shippingAddUri": "/customer/123/address/89ui",
"refUri": "orders/smallorder/xyz",
"type": "smallOrder"
},
{
"total": 135,
"messages": [
{ "visibility": true,"description": " your ordered delayed","id": "23456" },
{ "visibility": true,"description": "order initiated","id": "20459" }
],
"shippingAddUri": "/customer/678/address/90ny",
"refUri": "orders/smallorder/567z",
"type": "smallOrder"
}
],
"customerType": "householdCustomer",
"firstName": "Adam"
},
{
"lastName": "N",
"orders": [
{
"total": 125,
"messages": [ { "visibility": true,"description": " your ordered delivered","id": "2345" } ],
"shippingAddUri": "/customer/123/address/89ui",
"refUri": "orders/smallorder/xyz",
"type": "smallOrder"
},
{
"total": 234,
"messages": [
{ "visibility": true,"description": " your ordered delayed","id": "90" },
{ "visibility": true,"description": "order initiated","id": "34" }
],
"shippingAddUri": "/customer/uio/address/34bnmy",
"refUri": "orders/smallorder/xr7z",
"type": "smallOrder"
}
],
"customerType": "householdCustomer",
"firstName": "Thomas"
}
]
XSLT 3 在使用 Saxon EE 库功能('saxon:with-pedigree'、'saxon:pedigree(.)?容器和 'deep-update')。下面的 XSLT 将具有 'visibility' 属性值的数组对象标识为 'false',然后从父数组对象中排除所选对象。跟踪显示预期值,但 Saxon Deep 更新操作逻辑失败。标识和数组过滤按预期工作,但将过滤后的数组分配给属性未按预期工作,感谢您的意见。
JSON嵌入在XML
<list><![CDATA[
{
"customers":[
{
"customerType": "householdCustomer",
"firstName": "Adam",
"lastName": "L",
"orders": [
{
"type": "smallOrder",
"refUri": "orders/smallorder/xyz",
"total": 125.0,
"shippingAddUri": "/customer/123/address/89ui",
"messages": [
{
"visibility": true,
"description": " your ordered delivered",
"id": "2345"
},
{
"visibility": false,
"description": "supplier challenge - covid supply chain issues",
"id": "2167"
},
{
"visibility": false,
"description": "order routed to correct procurement",
"id": "2049"
},
{
"visibility": false,
"description": "order gone to wrong procurement center",
"id": "2047"
},
{
"visibility": true,
"description": "order initiated",
"id": "2045"
}
]
},
{
"type": "smallOrder",
"refUri": "orders/smallorder/567z",
"total": 135.0,
"shippingAddUri": "/customer/678/address/90ny",
"messages": [
{
"id": "23456",
"visibility": true,
"description": " your ordered delayed"
},
{
"id": "21677",
"visibility": false,
"description": "internal costcenter labor strike "
},
{
"id": "20459",
"visibility": true,
"description": "order initiated"
}
]
}
]
},
{
"customerType": "householdCustomer",
"firstName": "Thomas",
"lastName": "N",
"orders": [
{
"type": "smallOrder",
"refUri": "orders/smallorder/xyz",
"total": 125.0,
"shippingAddUri": "/customer/123/address/89ui",
"messages": [
{
"id": "2345",
"visibility": true,
"description": " your ordered delivered"
},
{
"id": "2167",
"visibility": false,
"description": "supplier challenge - covid supply chain issues"
},
{
"id": "2045",
"visibility": false,
"description": "order initiated"
}
]
},
{
"type": "smallOrder",
"refUri": "orders/smallorder/xr7z",
"total": 234.0,
"shippingAddUri": "/customer/uio/address/34bnmy",
"messages": [
{
"id": "90",
"visibility": true,
"description": " your ordered delayed"
},
{
"id": "67",
"visibility": false,
"description": "Postal delays, finding alternative route "
},
{
"id": "34",
"visibility": true,
"description": "order initiated"
}
]
}
]
},
{
"customerType": "corporateCustomer",
"corpName": "Telsoft Inc",
"orders": [
{},
{}
]
},
{
"customerType": "corporateCustomer",
"corpName": "Orange Inc",
"orders": [
{},
{}
]
},
{
"customerType": "corporateCustomer",
"corpName": "Notebook Inc",
"orders": [
{},
{}
]
}
]
}
]]>
</list>
XSLT 以本地方式转换 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:fn="http://www.w3.org/2005/xpath-functions" xmlns:saxon="http://saxon.sf.net/" xmlns:math="http://www.w3.org/2005/xpath-functions/math" xmlns:array="http://www.w3.org/2005/xpath-functions/array" xmlns:map="http://www.w3.org/2005/xpath-functions/map" xmlns:output="http://www.w3.org/2010/xslt-xquery-serialization" xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns:err="http://www.w3.org/2005/xqt-errors" xmlns:f="http://example.com/f" extension-element-prefixes="saxon" exclude-result-prefixes="array fn map math xhtml xs err saxon" version="3.0">
<xsl:output method="text" omit-xml-declaration="yes" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="list" name="xsl:initial-template">
<!-- read json from XML -->
<xsl:variable name="data" as="map(*)" select="parse-json(.)"/>
<!-- identify household customers -->
<xsl:variable name="householdCustomers" as="array(*)">
<saxon:array select="$data?customers?*[?customerType='householdCustomer']"/>
</xsl:variable>
<!-- produce hhsWithPedigree refrence structure using WithPedigree -->
<xsl:variable name="hhsWithPedigree" as="array(*)">
<saxon:array select="$householdCustomers => saxon:with-pedigree()"/>
</xsl:variable>
<!-- identify all objects with visibility as false' -->
<xsl:variable name="visibilityArrayWithFalse" as="array(*)">
<saxon:array select="saxon:map-search($hhsWithPedigree, 'visibility', function($v){ fn:matches(
xs:string($v), 'false') })"/>
</xsl:variable>
<!-- iterate through objects with 'visibility' attribute value as 'false' then identify root array
and exclude the selected objects -->
<xsl:for-each select="$visibilityArrayWithFalse?*?map">
<xsl:variable name="visiOne" select="saxon:pedigree(.)?container"/>
<saxon:deep-update
root = "$visiOne"
select = "."
action = " let $filteredValues := array:filter(., function($v) {map:get($v,'visibility') eq true() }), $noOfValues := count($filteredValues), $trace := trace($filteredValues, 'I m tracing') return $filteredValues "/>
</xsl:for-each>
<xsl:value-of select=" $householdCustomers => serialize(map { 'method' : 'json', 'use-character-maps' : map { '/' : '/' } })"/>
</xsl:template>
</xsl:stylesheet>
错误详细信息:
Error in saxon:deep-update/@root on line 31 column 222 of question-v1.xslt:
SENR0001: Cannot serialize a map using this output method
Focus
Context item: map{"visibility":false(), "description":"supplier challenge - covid supply c...", "id":"2167", }
Context position: 1
Local variables
$vv:v0 = coerced anon:f_1766145591
$householdCustomers = [map{"firstName":"Adam", "lastName":"L", "customerType":"householdCustomer", ...}, map{"firstName":"Thomas", "lastName":"N", "customerType":"householdCustomer", ...}, ]
invoked by unknown caller (class net.sf.saxon.expr.instruct.ForEach) at file:/C:/apps/xslt3/question-v1.xslt#26
In template rule with match="list" on line 6 of question-v1.xslt
Focus
Context item: /list
Context position: 1
Local variables
$vv:v0 = coerced anon:f_1766145591
$householdCustomers = [map{"firstName":"Adam", "lastName":"L", "customerType":"householdCustomer", ...}, map{"firstName":"Thomas", "lastName":"N", "customerType":"householdCustomer", ...}, ]
invoked by built-in template rule (text-only)
Cannot serialize a map using this output method
我认为部分错误是你使用了saxon:deep-update
而没有将其结果存储在一个可以带XDM映射或数组的变量中,即指令returns/outputs这样的映射或数组在里面xsl:for-each
的输出方法为 text
,您会收到错误消息,因为 saxon:deep-update
返回的结果序列化无法使用该方法 text
进行序列化。
我不太确定你想要实现什么,但我猜你不想输出 saxon:deep-update
的结果,你只希望它在你的地图上产生副作用。
阅读更多关于 saxon:deep-update
的内容,我想知道您是否需要所有明确的血统使用,以下
<xsl:template match="list" name="xsl:initial-template">
<!-- read json from XML -->
<xsl:variable name="data" as="map(*)" select="parse-json(.)"/>
<!-- identify household customers -->
<xsl:variable name="householdCustomers" select="array { $data?customers?*[?customerType='householdCustomer']}"/>
<xsl:variable name="update-result" as="item()*">
<saxon:deep-update root="$householdCustomers"
select="?*?orders?*?messages"
action="array:filter(., function($v) { $v?visibility })"/>
</xsl:variable>
<xsl:value-of select=" $update-result => serialize(map { 'method' : 'json', 'indent' : true(), 'use-character-maps' : map { '/' : '/' } })"/>
</xsl:template>
产出
[
{
"lastName": "L",
"orders": [
{
"total": 125,
"messages": [
{ "visibility": true,"description": " your ordered delivered","id": "2345" },
{ "visibility": true,"description": "order initiated","id": "2045" }
],
"shippingAddUri": "/customer/123/address/89ui",
"refUri": "orders/smallorder/xyz",
"type": "smallOrder"
},
{
"total": 135,
"messages": [
{ "visibility": true,"description": " your ordered delayed","id": "23456" },
{ "visibility": true,"description": "order initiated","id": "20459" }
],
"shippingAddUri": "/customer/678/address/90ny",
"refUri": "orders/smallorder/567z",
"type": "smallOrder"
}
],
"customerType": "householdCustomer",
"firstName": "Adam"
},
{
"lastName": "N",
"orders": [
{
"total": 125,
"messages": [ { "visibility": true,"description": " your ordered delivered","id": "2345" } ],
"shippingAddUri": "/customer/123/address/89ui",
"refUri": "orders/smallorder/xyz",
"type": "smallOrder"
},
{
"total": 234,
"messages": [
{ "visibility": true,"description": " your ordered delayed","id": "90" },
{ "visibility": true,"description": "order initiated","id": "34" }
],
"shippingAddUri": "/customer/uio/address/34bnmy",
"refUri": "orders/smallorder/xr7z",
"type": "smallOrder"
}
],
"customerType": "householdCustomer",
"firstName": "Thomas"
}
]