简体   繁体   中英

XSLT 3 Saxon, filtering unwanted array elements using deep-update and filter

XSLT 3 is causing "SENR0001: Cannot serialize a map using this output method" error while transforming JSON natively using Saxon EE library capabilities ( 'saxon:with-pedigree', 'saxon:pedigree(.)?container, and 'deep-update'). Below XSLT identifies array objects with 'visibility' attribute value as 'false' then excludes the selected objects from the parent array object. the trace is showing expected values but Saxon Deep update action logic is failing. Identification and array filtering are working as expected but assigning the filtered array to attribute is not working as expected, appreciate your input.

JSON Embedded in 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 to transform JSON natively.

<?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 Detail:

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

I think part of the error is that you use the saxon:deep-update without storing its result in a variable that can take an XDM map or array, that instruction returns/outputs such a map or array inside of the xsl:for-each and with the output method being text you are getting the error because the serialization of the result returned by saxon:deep-update can't be serialized with that method text .

I am not quite sure what you want to achieve but I guess you don't want to output the result of saxon:deep-update , you just want its side effect on your map(s).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM