getLegendGraphic in Geoserver does not display title - legend

When a SLD have a dynamic fill color or dynamic stroke color, then the title is not displayed in the Legend when a legend is requested from Geoserver.
See example below:
<?xml version="1.0" encoding="UTF-8"?>
<StyledLayerDescriptor xmlns="http://www.opengis.net/sld" xmlns:se="http://www.opengis.net/se" xmlns:ogc="http://www.opengis.net/ogc" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.1.0/StyledLayerDescriptor.xsd" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<NamedLayer>
<se:Name>prop_land_use</se:Name>
<UserStyle>
<se:Name>prop_land_use</se:Name>
<se:FeatureTypeStyle>
<se:Rule>
<se:Name>default</se:Name>
<se:Description>
<se:Title>Property Land Use</se:Title>
</se:Description>
<se:MinScaleDenominator>0.0</se:MinScaleDenominator>
<se:MaxScaleDenominator>300000.0</se:MaxScaleDenominator>
<se:PolygonSymbolizer uom="http://www.opengeospatial.org/se/units/metre">
<se:Fill>
<se:SvgParameter name="fill">
<ogc:PropertyName>lnduse_clr</ogc:PropertyName>
</se:SvgParameter>
<se:SvgParameter name="fill-opacity">0.1</se:SvgParameter>
</se:Fill>
<se:Stroke>
<se:SvgParameter name="stroke">
<ogc:PropertyName>lnduse_clr</ogc:PropertyName>
</se:SvgParameter>
<se:SvgParameter name="stroke-width">0.2</se:SvgParameter>
<se:SvgParameter name="stroke-linecap">
<ogc:Literal>round</ogc:Literal>
</se:SvgParameter>
<se:SvgParameter name="stroke-linejoin">
<ogc:Literal>round</ogc:Literal>
</se:SvgParameter>
</se:Stroke>
</se:PolygonSymbolizer>
</se:Rule>
</se:FeatureTypeStyle>
</UserStyle>
</NamedLayer>
</StyledLayerDescriptor>

Related

Can someone explain this 'Get all Numeric Elements' operator Predicate Filter?

Trying to get elements with a value that is numeric, including zero.
sample xml
<?xml version="1.0" encoding="utf-8"?>
<PRODUCTS xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<PRODUCT>
<REFERENCE>10</REFERENCE>
<ATTRIBUTES />
<TITLE>fdg</TITLE>
<ACTIVE>1</ACTIVE>
<DELETE>0</DELETE>
<STOCK>10</STOCK>
<WEIGHT>0.00</WEIGHT>
<MODEL>f</MODEL>
<EAN />
<MPN />
<ISBN />
<UPC />
<PRICE>10.000</PRICE>
<SALE_PRICE>10.000</SALE_PRICE>
<RRP_PRICE>0.000</RRP_PRICE>
<COST_PRICE>0.000</COST_PRICE>
<VAT_RATE>0.00</VAT_RATE>
</PRODUCT>
</PRODUCTS>
Expected Output
<?xml version="1.0" encoding="utf-8"?>
<Values>
<REFERENCE>10</REFERENCE>
<ACTIVE>1</ACTIVE>
<DELETE>0</DELETE>
<STOCK>10</STOCK>
<WEIGHT>0.00</WEIGHT>
<PRICE>10.000</PRICE>
<SALE_PRICE>10.000</SALE_PRICE>
<RRP_PRICE>0.000</RRP_PRICE>
<COST_PRICE>0.000</COST_PRICE>
<VAT_RATE>0.00</VAT_RATE>
</Values>
'all numeric' [number()] returns 0 as single predicate expression
<xsl:template match="/">
<Value>
<xsl:for-each select="//*[number()]">
<xsl:element name="{local-name()}">
<xsl:value-of select="."/>
</xsl:element>
Excluding elements without descendants produces expected (non-zero) numbers
<xsl:for-each select="//*[number() and not(descendant::*)]">
Get all 0 using *[number() or format-number(text(),0)='0']
non-zero numbers
<xsl:for-each select="//*[number() and not(descendant::*)]">
all numbers
<xsl:for-each select="//*[number() or format-number(text(),0)='0']">
Adding an additional and or or seems to produce the expected.
Why does select="*[number()]" output 0 results, until an and/or is added?
The rules for evaluating the expression in a predicate are as follows:
If the expression evaluates to a number $n, then the result is true if $n is equal to the context position; IOW, it is as if you have written [position() = $n];
Otherwise the expression is evaluated as a boolean.
To demonstrate, consider the following simplified example:
XML
<items>
<item>0</item>
<item>x</item>
<item>3</item>
<item>y</item>
<item>4</item>
</items>
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/items">
<xsl:copy>
<xsl:copy-of select="item[number()]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>3</item>
</items>
Here only the item whose value, when converted to a number, matches the item's position was copied.
If instead you do:
<xsl:copy-of select="item[number() or false()]"/>
then the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>3</item>
<item>4</item>
</items>
because now the expression is evaluated as a boolean and any number other than 0 will be evaluated as true.
In order to copy all items with a "numeric" value, you need to do:
<xsl:copy-of select="item[number() = number()]"/>
to get:
<?xml version="1.0" encoding="UTF-8"?>
<items>
<item>0</item>
<item>3</item>
<item>4</item>
</items>
This excludes the items whose value cannot be converted to a number - because NaN is not equal to anything, including itself.
When you evaluate number() in a predicate, it is behaving as if you had specified the short-hand for the position. i.e. for <REFERENCE>10</REFERENCE> it was as if you had tested //*[10] or the longer form //*[position()=10] and that element is at position 1 and not 10, so it didn't select any elements.
Another way to evaluate a boolean expression and test if they are numeric would be to use:
[number() eq number()]

Find element or attribute value anywhere in XML

I am trying to find the value of an element / attribute regardless of where it exists in the XML.
XML:
<?xml version="1.0" encoding="UTF-8"?>
<cXML payloadID="12345677-12345567" timestamp="2017-07-26T09:11:05">
<Header>
<From>
<Credential domain="1212">
<Identity>01235 </Identity>
<SharedSecret/>
</Credential>
</From>
<To>
<Credential domain="1212">
<Identity>01234</Identity>
</Credential>
</To>
<Sender>
<UserAgent/>
<Credential domain="8989">
<Identity>10678</Identity>
<SharedSecret>Testing123</SharedSecret>
</Credential>
</Sender>
</Header>
<Request deploymentMode="Prod">
<ConfirmationRequest>
<ConfirmationHeader noticeDate="2017-07-26T09:11:05" operation="update" type="detail">
<Total>
<Money>0.00</Money>
</Total>
<Shipping>
<Description>Delivery</Description>
</Shipping>
<Comments>WO# generated</Comments>
</ConfirmationHeader>
<OrderReference orderDate="2017-07-25T15:22:11" orderID="123456780000">
<DocumentReference payloadID="5678-4567"/>
</OrderReference>
<ConfirmationItem quantity="1" lineNumber="1">
<ConfirmationStatus quantity="1" type="detail">
<ItemIn quantity="1">
<ItemID>
<SupplierPartID>R954-89</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">0.00</Money>
</UnitPrice>
<Description>Test Descritpion 1</Description>
<UnitOfMeasure>QT</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</ConfirmationStatus>
</ConfirmationItem>
<ConfirmationItem quantity="1" lineNumber="2">
<ConfirmationStatus quantity="1" type="detail">
<ItemIn quantity="1">
<ItemID>
<SupplierPartID>Y954-89</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">0.00</Money>
</UnitPrice>
<Description>Test Descritpion 2</Description>
<UnitOfMeasure>QT</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</ConfirmationStatus>
</ConfirmationItem>
</ConfirmationRequest>
</Request>
</cXML>
I want to get the value of the payloadID on the DocumentReference element. This is what I have tried so far:
BEGIN
Declare #Xml xml
Set #Xml = ('..The XML From Above..' as xml)
END
--no value comes back
Select c.value('(/*/DocumentReference/#payloadID)[0]','nvarchar(max)') from #Xml.nodes('//cXML') x(c)
--no value comes back
Select c.value('#payloadID','nvarchar(max)') from #Xml.nodes('/cXML/*/DocumentReference') x(c)
--check if element exists and it does
Select #Xml.exist('//DocumentReference');
I tried this in an xPath editor: //DocumentReference/#payloadID
This does work, but I am not sure what the equivalent syntax is in SQL
Calling .nodes() (like suggested in comment) is an unecessary overhead...
Better try it like this:
SELECT #XML.value('(//DocumentReference/#payloadID)[1]','nvarchar(max)')
And be aware, that XPath starts counting at 1. Your example with [0] cannot work...
--no value comes back
Select c.value('(/*/DocumentReference/#payloadID)[0]','nvarchar(max)') from...

XSLT Outer Bracket Node Inside Inner Bracket

I have the following XML:
<Root>
<PersonSettings>
<Type Drinks="1">A</Type>
<Type Drinks="2">B</Type>
<Type Drinks="3">C</Type>
<LowestAge>20</LowestAge>
<MaxAge>49</MaxAge>
</PersonSettings>
<PersonSettings>
<Type Drinks="5">A</Type>
<Type Drinks="8">B</Type>
<Type Drinks="1">C</Type>
<LowestAge>50</LowestAge>
<MaxAge>90</MaxAge>
</PersonSettings>
<Person Alive="Yes">
<Type>A</Type>
<Age>23</Age>
</Person>
<Person Alive="Yes">
<Type>B</Type>
<Age>50</Age>
</Person>
<Person Alive="Yes">
<Type>C</Type>
<Age>51</Age>
</Person>
<Person Alive="Yes">
<Type>A</Type>
<Age>70</Age>
</Person>
</Root>
And the following XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="utf-8" indent="no"/>
<xsl:template match="/">
<PersonsOneDrink>
<xsl:value-of select="(count(/Root/Person[#Alive = 'Yes' and /Root/PersonSettings[**(Person/Age)** >= LowestAge and **(Person/Age)** <= MaxAge]/Type[. = **(Person/Type)** and #Drinks = '1']))"/>
</PersonsOneDrink>
</xsl:template>
</xsl:stylesheet>
What I want to do in this example is count the number of people with one drink, that are alive. I have different settings depending on the Type of Person and the Age of such person. For example Type A has one drink if between 20 and 49 years of age, while type C has one drink if between 50 to 90 years. The problem I find is that I cannot reference the outer node when going inside a second set of brackets. Is there any way to create a variable on the fly?
P.S: The parts with * * () * * are where I would like to reference the outer node.
I don't think this can be done with a single count() expression, applied from the context of the root.
The problem here is that you need to refer to the values of Person within the predicate comparing them to the values of the prospective PersonSettings. For this, you need to use the current() function - but in order to have the current() function refer to Person, you must first make Person the context node.
Here is a suggested approach that writes a character for each Person that passes the test into a variable. This eliminates the need to convert the variable into a node-set before counting it:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Root">
<xsl:variable name="v1">
<xsl:for-each select="Person">
<xsl:if test="#Alive = 'Yes' and /Root/PersonSettings[LowestAge <= current()/Age and MaxAge >= current()/Age]/Type[. = current()/Type]/#Drinks = 1">
<xsl:text>Y</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<PersonsOneDrink>
<xsl:value-of select="string-length($v1)"/>
</PersonsOneDrink>
</xsl:template>
</xsl:stylesheet>
Result
<?xml version="1.0" encoding="UTF-8"?>
<PersonsOneDrink>2</PersonsOneDrink>
A more general solution - suitable if you want to perform several queries on the supplied data - would start by rewriting the input and assigning each Person the corresponding amount of drinks .
Here we will construct a variable that contains:
<Person>
<Type>A</Type>
<Age>23</Age>
<Drinks>1</Drinks>
</Person>
<Person>
<Type>B</Type>
<Age>50</Age>
<Drinks>8</Drinks>
</Person>
<Person>
<Type>C</Type>
<Age>51</Age>
<Drinks>1</Drinks>
</Person>
<Person>
<Type>A</Type>
<Age>70</Age>
<Drinks>5</Drinks>
</Person>
Then, once the variable is converted into a node-set, it is trivial to get the number of persons with any amount of drinks:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/Root">
<!-- first pass -->
<xsl:variable name="persons-rtf">
<xsl:for-each select="Person">
<xsl:copy>
<xsl:copy-of select="*"/>
<Drinks>
<xsl:value-of select="/Root/PersonSettings[LowestAge <= current()/Age and MaxAge >= current()/Age]/Type[. = current()/Type]/#Drinks"/>
</Drinks>
</xsl:copy>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="persons" select="exsl:node-set($persons-rtf)/Person"/>
<!-- output -->
<results>
<PersonsOneDrink>
<xsl:value-of select="count($persons[Drinks = 1])"/>
</PersonsOneDrink>
</results>
</xsl:template>
</xsl:stylesheet>

How to handle For each condition in Data weaver: Mule

I'm getting struggle in looping the entries in data weaver. Below is the Input and the expected response.
Not sure how to make loop(I need to get RecordEntry and each entry with 'IndividualEntry') .
Input xml : Record entry tag in input xml is 3, but I might get many. So need to make a loop as dynamic.
<?xml version="1.0" encoding="UTF-8"?>
<Records>
<storenumber />
<calculated>false</calculated>
<subTotal>12</subTotal>
<RecordsEntries>
<RecordEntry>
<deliverycharge>30.0</deliverycharge>
<entryNumber>8</entryNumber>
<Value>true</Value>
</RecordEntry>
<RecordEntry>
<deliverycharge>20.0</deliverycharge>
<entryNumber>7</entryNumber>
<Value>false</Value>
</RecordEntry>
<RecordEntry>
<deliverycharge>1.0</deliverycharge>
<entryNumber>6</entryNumber>
<Value>false</Value>
</RecordEntry>
</RecordsEntries>
</Records>
Expected Response ( I'm expecting the below response)
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<StoreID />
<Total>false</Total>
<IndividualEntry>
<Number>8</Number>
<DeliverCharge>30.0</DeliverCharge>
</IndividualEntry>
<IndividualEntry>
<Number>7</Number>
<DeliverCharge>20.0</DeliverCharge>
</IndividualEntry>
<IndividualEntry>
<Number>6</Number>
<DeliverCharge>1.0</DeliverCharge>
</IndividualEntry>
</order>
</orders>
My Data weaver Transformation as below
%dw 1.0
%output application/xml
---
{
orders: {
order: {
StoreID:payload.Records.storenumber,
Total: payload.Records.calculated,
IndividualEntry: payload.Records.RecordsEntries.*RecordEntry map {
Number:$.entryNumber,
DeliverCharge:$.deliverycharge
}
}
}
}
Currently I'm getting response as below ( I don't know how to make each Record entry as a IndividualEntry tag, and also here element tag is added in extra which is not required in my case)
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order>
<StoreID />
<Total>false</Total>
<IndividualEntry>
<element>
<Number>8</Number>
<DeliverCharge>30.0</DeliverCharge>
</element>
<element>
<Number>7</Number>
<DeliverCharge>20.0</DeliverCharge>
</element>
<element>
<Number>6</Number>
<DeliverCharge>1.0</DeliverCharge>
</element>
</IndividualEntry>
</order>
</orders>
Could any one help me in fix this. Thanks in advance.
One way to do it:
orders: {
order: {
StoreID: payload.Records.storenumber,
Total: payload.Records.calculated,
(payload.Records.RecordsEntries.*RecordEntry map {
IndividualEntry: {
Number:$.entryNumber,
DeliverCharge:$.deliverycharge
}
})
}
}
Inside an object when you put an expression between parenthesis that returns an array of key-value pairs it is evaluated and used to fill the object.
See section5.1.3. Dynamic elements in https://developer.mulesoft.com/docs/dataweave

Need to group xsl:for-each-group with Muenchian method

I am not able to retrieve unique list by applying Muenchian method. I am trying to group based on "Series Title" attribute
Sample Input XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Distribution>
<ManifestHeader>
<Assets>
<Asset>
<ID>23341528</ID>
<CreateDate>2008-01-14T17:02:01Z</CreateDate>
<MetaDatas>
<MetaData Name="psa.orig.source.showTitle">Green Home 2008</MetaData>
<MetaData Name="displayRunTime">00:01</MetaData>
<MetaData Name="Series Title">Desperate Landscapes</MetaData>
</MetaDatas>
</Asset>
<Asset>
<ID>23341529</ID>
<CreateDate>2010-08-23T15:44:58Z</CreateDate>
<MetaDatas>
<MetaData Name="psa.orig.source.showTitle">Urban Oasis 2010</MetaData>
<MetaData Name="displayRunTime">00:02</MetaData>
<MetaData Name="Series Title">Toy Hunter</MetaData>
</MetaDatas>
</Asset>
<Asset>
<ID>23377202</ID>
<CreateDate>2007-05-18T07:40:25Z</CreateDate>
<MetaDatas>
<MetaData Name="webSeries"/>
<MetaData Name="psa.orig.source.showTitle">Cool Tools</MetaData>
<MetaData Name="displayRunTime">00:20</MetaData>
<MetaData Name="Series Title">Desperate Landscapes</MetaData>
</MetaDatas>
</Asset>
</Assets>
</ManifestHeader>
</Distribution>
XLST:
<xsl:key name="keySeriesName" match="MetaData[#Name='Series Title']" use="text()" />
<xsl:for-each select="MetaData[#Name='Series Title'][generate-id() =
generate-id(key('keySeriesName', text())[1])]">
also tried:
<xsl:for-each select="MetaData[#Name='Series Title'][count(. | key('keySeriesName',text())[1]) = 1]">
anyhelp would be appreciated
Thanks in advance
Since the <MetaData> elements are children of <MetaData> and you are trying to search across the entire collection of them within the document, you are going to need to adjust your XPath to ensure that you are addressing all of them:
/Distribution/ManifestHeader/Assets/Asset/MetaDatas/MetaData
[#Name='Series Title'][generate-id() =
generate-id(key('keySeriesName', text())[1])]
or you could use the shorter, but less efficient:
//MetaData[#Name='Series Title'][generate-id() =
generate-id(key('keySeriesName', text())[1])]