问题
I am trying to get the enum value of the corresponding string. I am translating one XML into another.
For example, the source element is
<VehicleBodyType>Van</VehicleBodyType>
I need to transform it to
<VehicleTypeCode>5</VehicleTypeCode>
This is in an XSD:
<xs:simpleType name="VehicleBodyType">
<xs:restriction base="xs:string">
<xs:enumeration value="NotProvided" />
<xs:enumeration value="NotApplicable" />
<xs:enumeration value="PassengerCar" />
<xs:enumeration value="TruckPickupOrPassengerTruck" />
<xs:enumeration value="Van" />
<xs:enumeration value="TruckSingleUnitTruck2Axles" />
<xs:enumeration value="MotorHomeRecreationalVehicle" />
</xs:restriction>
</xs:simpleType>
I tried this:
<VehicleTypeCode>
<xsl:template match="xs:simpleType[@name='VehicleBodyType']/xs:restriction">
<xsl:for-each select="xs:enumeration">
<xsl:value-of select="@value"/>
</xsl:for-each>
</xsl:template>
</VehicleTypeCode>
but would get an error indicating that I can't do a template as a child of 'VehicleTypeCode' element.
I would prefer to use an XSD, but I can put this into the XSLT as well, if that makes it easier. I don't even know if the for-each is valid, but I found it on here and it looks like what I want.
Here is a sample of the source xml:
<?xml version="1.0" encoding="UTF-8"?>
<Crash>
<Vehicles>
<Vehicle>
<VehicleBodyType>Van</VehicleBodyType>
<VehicleColor>Red</VehicleColor>
</Vehicle>
</Vehicles>
</Crash>
Here the stripped down xslt i'm using:
<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:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" exclude-result-prefixes="xsl xs fn xsi">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Crash" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<CrashEntity>
<WorkZoneWorkers>
<xsl:value-of select="WorkersPresentCde"/>
</WorkZoneWorkers>
<xsl:choose>
<xsl:when test="not(Vehicles/Vehicle)">
<CrashUnits/>
</xsl:when>
<xsl:otherwise>
<CrashUnits>
<xsl:apply-templates select="Vehicles/Vehicle" />
</CrashUnits>
</xsl:otherwise>
</xsl:choose>
</CrashEntity>
</xsl:template>
<!-- Vehicles/Vehicle -->
<xsl:template match="Vehicles/Vehicle">
<CrashUnitsEntity>
<VehicleTypeCode>
<xsl:value-of select="VehicleBodyType"/>
</VehicleTypeCode>
<!--Can't use a template within a template-->
<!--<xsl:template match="xs:simpleType[@name='VehicleBodyType']/xs:restriction">
<VehicleTypeCode>
<xsl:value-of select="count(xs:enumeration[@value = 'Van']/preceding-sibling::xs:enumeration) + 1"/>
</VehicleTypeCode>
</xsl:template>-->
<!--Can't use a template within a template (original attempt)-->
<!--<VehicleTypeCode>
<xsl:template match="xs:simpleType[@name=$data]/xs:restriction">
<xsl:for-each select="xs:enumeration">
<xsl:value-of select="@value"/>
</xsl:for-each>
</xsl:template>
</VehicleTypeCode>-->
<!--Try to call a function-->
<VehicleTypeCode function="Enum1">
<xsl:call-template name="getEnum1">
<xsl:with-param name="type" select="VehicleBodyType"/>
<xsl:with-param name="data" select="VehicleBodyType"/>
</xsl:call-template>
</VehicleTypeCode>
<!--Try to call a function-->
<VehicleTypeCode function="Enum2">
<xsl:call-template name="getEnum2">
<xsl:with-param name="type" select="VehicleBodyType"/>
<xsl:with-param name="data" select="VehicleBodyType"/>
</xsl:call-template>
</VehicleTypeCode>
<Vehicle>
<UnitNumber>
<xsl:value-of select="@VehicleNumber"/>
</UnitNumber>
</Vehicle>
</CrashUnitsEntity>
</xsl:template>
<!-- ##################################### functions ##################################### -->
<!-- Can't call a template inside another template-->
<xsl:template name="getEnum1">
<xsl:param name="type"/>
<xsl:param name="data"/>
<xsl:if test="$data">
<!--<xsl:template match="xs:simpleType[@name=$type]/xs:restriction">
<xsl:for-each select="xs:enumeration">
<xsl:value-of select="@value"/>
</xsl:for-each>
</xsl:template>-->
</xsl:if>
</xsl:template>
<!-- Can't call a template inside another template-->
<xsl:template name="getEnum2">
<xsl:param name="type"/>
<xsl:param name="data"/>
<xsl:if test="$data">
<!--<xsl:template match="xs:simpleType[@name=$type]/xs:restriction">
<xsl:value-of select="count(xs:enumeration[@value = $data]/preceding-sibling::xs:enumeration) + 1"/>
</xsl:template>-->
</xsl:if>
</xsl:template>
<xs:simpleType name="VehicleBodyType">
<xs:restriction base="xs:string">
<xs:enumeration value="NotProvided" />
<xs:enumeration value="NotApplicable" />
<xs:enumeration value="PassengerCar" />
<xs:enumeration value="Van" />
<xs:enumeration value="Truck" />
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="VehicleColor">
<xs:restriction base="xs:string">
<xs:enumeration value="NotProvided" />
<xs:enumeration value="Red" />
<xs:enumeration value="Green" />
<xs:enumeration value="Blue" />
</xs:restriction>
</xs:simpleType>
</xsl:stylesheet>
Expected output xml:
<?xml version="1.0" encoding="UTF-8"?>
<CrashEntity>
<WorkZoneWorkers/>
<CrashUnits>
<CrashUnitsEntity>
<VehicleTypeCode>4</VehicleTypeCode>
<VehicleColor>2</VehicleColor>
</CrashUnitsEntity>
</CrashUnits>
</CrashEntity>
来源:https://stackoverflow.com/questions/52652446/get-enum-value-from-string-using-xslt-and-xsd