Transformation with Saxon 6.5.5 and XLST does not

2019-08-07 05:36发布

I want to transform this xml:

    <?xml version="1.0" encoding="utf-8"?>
<KNX xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" CreatedBy="ETS4" ToolVersion="ETS 4.1.2 (Build 3013)" xmlns="http://knx.org/xml/project/11">
  <Project Id="P-065C">
    <Installations>
      <Installation InstallationId="0" Name="" BCUKey="4294967295" DefaultLine="P-065C-0_L-2" IPRoutingMulticastAddress="224.0.23.12" SplitType="None" CompletionStatus="Undefined">
        <Topology>
          <Area Id="P-065C-0_A-0" Name="Backbone Bereich" Address="0" CompletionStatus="Undefined">
            <Line Id="P-065C-0_L-0" Name="Bereichslinie" Address="0" MediumTypeRefId="MT-5" DomainAddress="0" DomainAddressIsChecked="0" CompletionStatus="Undefined" IPRoutingMulticastAddress="224.0.23.12" MulticastTTL="16" />
          </Area>
          <Area Id="P-065C-0_A-1" Name="Neuer Bereich" Address="1" CompletionStatus="Undefined">
            <Line Id="P-065C-0_L-1" Name="Hauptlinie" Address="0" MediumTypeRefId="MT-5" DomainAddress="0" DomainAddressIsChecked="0" CompletionStatus="Undefined" IPRoutingMulticastAddress="224.0.23.12" MulticastTTL="16" />
            <Line Id="P-065C-0_L-2" Name="Neue Linie" Address="1" MediumTypeRefId="MT-0" DomainAddress="0" DomainAddressIsChecked="0" CompletionStatus="Undefined" IPRoutingMulticastAddress="224.0.23.12" MulticastTTL="16">
              <DeviceInstance Id="P-065C-0_DI-1" ProductRefId="M-0002_H-2CDG.20110.20085.20R0011-1_P-2CDG.20110.20085.20R0011" Hardware2ProgramRefId="M-0002_H-2CDG.20110.20085.20R0011-1_HP" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0" />
              <DeviceInstance Id="P-065C-0_DI-2" ProductRefId="M-0002_H-2CDG110061R0011-1_P-2CDG.20110.20061.20R0011" Hardware2ProgramRefId="M-0002_H-2CDG110061R0011-1_HP-A035-10-377F" Address="0" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0" />
              <DeviceInstance Id="P-065C-0_DI-3" ProductRefId="M-0008_H-8.20.2F.2F.2018500-1-O0001_P-185.2000" Hardware2ProgramRefId="M-0008_H-8.20.2F.2F.2018500-1-O0001_HP-1058-01-D423-O0001" Address="1" LastModified="2012-09-07T14:20:33" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0">
                <ComObjectInstanceRefs>
                  <ComObjectInstanceRef RefId="M-0008_A-1058-01-D423-O0001_O-0_R-5" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-1" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0008_A-1058-01-D423-O0001_O-1_R-11" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-1" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0008_A-1058-01-D423-O0001_O-2_R-23" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-2" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0008_A-1058-01-D423-O0001_O-3_R-26" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-2" />
                    </Connectors>
                  </ComObjectInstanceRef>
                </ComObjectInstanceRefs>
              </DeviceInstance>
              <DeviceInstance Id="P-065C-0_DI-6" ProductRefId="M-0048_H-1319201-2_P-1319201" Hardware2ProgramRefId="M-0048_H-1319201-2_HP-131C-12-4C9E" Address="2" LastModified="2012-09-07T12:16:26" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0">
                <ComObjectInstanceRefs>
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-12_R-209" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-13_R-13" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-14_R-14" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-15_R-15" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-16_R-63" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-17_R-17" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-4_R-68" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-40_R-215" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-1_R-2" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-3" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-0_R-1" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-3" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-7_R-8" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0048_A-131C-12-4C9E_O-8_R-122" IsActive="1" />
                </ComObjectInstanceRefs>
              </DeviceInstance>
              <DeviceInstance Id="P-065C-0_DI-5" ProductRefId="M-0008_H-8.20.2F.2F.20570.2000-1_P-570.2000" Hardware2ProgramRefId="M-0008_H-8.20.2F.2F.20570.2000-1_HP" Address="3" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0" />
              <DeviceInstance Id="P-065C-0_DI-7" ProductRefId="M-0007_H-2CDG.20110.20079.20R0011-1-O0002_P-6197.2F22" Hardware2ProgramRefId="M-0007_H-2CDG.20110.20079.20R0011-1-O0002_HP-A043-12-5DB8-O0002" Address="4" LastModified="2012-09-07T14:20:45" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0">
                <ComObjectInstanceRefs>
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-10_R-2438" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-1" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-12_R-2319" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-13_R-2443" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-34_R-2433" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-35_R-2440" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-2" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-38_R-2450" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-59_R-2432" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0007_A-A043-12-5DB8-O0002_O-37_R-2316" DatapointType="DPST-3-7" IsActive="1" />
                </ComObjectInstanceRefs>
              </DeviceInstance>
              <DeviceInstance Id="P-065C-0_DI-8" ProductRefId="M-0008_H-8.20.2F.2F.20880.20xx-1_P-880.20xx" Hardware2ProgramRefId="M-0008_H-8.20.2F.2F.20880.20xx-1_HP-A003-01-737E" Address="5" LastModified="2012-09-07T12:16:43" CompletionStatus="Undefined" IndividualAddressLoaded="0" ApplicationProgramLoaded="0" ParametersLoaded="0" CommunicationPartLoaded="0" MediumConfigLoaded="0" IsCommunicationObjectVisibilityCalculated="1" Broken="0">
                <ComObjectInstanceRefs>
                  <ComObjectInstanceRef RefId="M-0008_A-A003-01-737E_O-0_R-0" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-4" />
                    </Connectors>
                  </ComObjectInstanceRef>
                  <ComObjectInstanceRef RefId="M-0008_A-A003-01-737E_O-1_R-1" IsActive="1" />
                  <ComObjectInstanceRef RefId="M-0008_A-A003-01-737E_O-2_R-2" IsActive="1">
                    <Connectors>
                      <Send GroupAddressRefId="P-065C-0_GA-4" />
                    </Connectors>
                  </ComObjectInstanceRef>
                </ComObjectInstanceRefs>
              </DeviceInstance>
            </Line>
          </Area>
        </Topology>
        <Buildings>
          <BuildingPart Id="P-065C-0_BP-0" Name="Hauptgebäude" Type="Building" CompletionStatus="Undefined">
            <BuildingPart Id="P-065C-0_BP-1" Name="Vordergebäude" Type="BuildingPart" CompletionStatus="Undefined" />
            <BuildingPart Id="P-065C-0_BP-2" Name="Rückgebäude" Type="BuildingPart" CompletionStatus="Undefined">
              <BuildingPart Id="P-065C-0_BP-3" Name="Erdgeschoss" Type="Floor" CompletionStatus="Undefined" />
              <BuildingPart Id="P-065C-0_BP-4" Name="1.Etage" Type="Floor" CompletionStatus="Undefined">
                <BuildingPart Id="P-065C-0_BP-5" Name="Küche" Type="Room" CompletionStatus="Undefined" />
                <BuildingPart Id="P-065C-0_BP-6" Name="Büro Poolfahrzeuge" Type="Room" CompletionStatus="Undefined" />
                <BuildingPart Id="P-065C-0_BP-7" Name="Büro Studenten" Type="Room" CompletionStatus="Undefined">
                  <DeviceInstanceRef RefId="P-065C-0_DI-1" />
                  <DeviceInstanceRef RefId="P-065C-0_DI-2" />
                  <DeviceInstanceRef RefId="P-065C-0_DI-5" />
                  <DeviceInstanceRef RefId="P-065C-0_DI-6" />
                  <DeviceInstanceRef RefId="P-065C-0_DI-8" />
                  <DeviceInstanceRef RefId="P-065C-0_DI-3" />
                  <DeviceInstanceRef RefId="P-065C-0_DI-7" />
                </BuildingPart>
              </BuildingPart>
            </BuildingPart>
          </BuildingPart>
        </Buildings>
        <GroupAddresses>
          <GroupRanges>
            <GroupRange Id="P-065C-0_GR-1" Name="Zentralfunktionen" RangeStart="1" RangeEnd="2047">
              <GroupRange Id="P-065C-0_GR-3" Name="Sensorwerte auslesen" RangeStart="256" RangeEnd="511">
                <GroupAddress Id="P-065C-0_GA-3" Address="256" Name="Helligkeitssensor" />
                <GroupAddress Id="P-065C-0_GA-4" Address="257" Name="Bewegungsmelder" />
              </GroupRange>
              <GroupRange Id="P-065C-0_GR-2" Name="Licht steuern" RangeStart="1" RangeEnd="255">
                <GroupAddress Id="P-065C-0_GA-1" Address="1" Name="Glühbirne 1" />
                <GroupAddress Id="P-065C-0_GA-2" Address="2" Name="Glühbirne 2" />
              </GroupRange>
            </GroupRange>
          </GroupRanges>
        </GroupAddresses>
      </Installation>
    </Installations>
  </Project>
</KNX>

with this stylesheet

    <xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="iso-8859-1" indent="yes"/>
<xsl:template match="/"  xmlns:b="http://knx.org/xml/project/10">
<xsl:for-each select="b:KNX/b:Project/b:Installations/b:Installation/b:Topology">
<datapoints>
<xsl:for-each select="b:Area/b:Line/b:DeviceInstance/b:ComObjectInstanceRefs/b:ComObjectInstanceRef">
<xsl:sort select="b:Connectors/b:Send/@GroupAddressRefId"/>
<xsl:if test="not(preceding::b:Connectors/b:Send/@GroupAddressRefId = current()/b:Connectors/b:Send/@GroupAddressRefId)">
<xsl:for-each select="b:Connectors">
<xsl:variable name="verz" select="document(concat(substring(../@RefId,0,7),'/',substring-before(../@RefId, '_O'), '.xml'))/b:KNX/b:ManufacturerData/b:Manufacturer/b:ApplicationPrograms/b:ApplicationProgram/b:Static/b:ComObjectTable/b:ComObject[@Id = ../../b:ComObjectRefs/b:ComObjectRef[@Id = current()/../@RefId]/@RefId]" /> 
<xsl:variable name="grosse"> 
  <xsl:choose>
    <xsl:when test="substring-after($verz/@ObjectSize,' ') = 'Bytes'">
    <xsl:value-of select="substring-before($verz/@ObjectSize,' ')*8" /> 
    </xsl:when>
    <xsl:otherwise>
    <xsl:value-of select="substring-before($verz/@ObjectSize,' ')" /> 
    </xsl:otherwise>
  </xsl:choose>
</xsl:variable>
<xsl:variable name="master" select="document('knx_master.xml')/b:KNX/b:MasterData/b:DatapointTypes/b:DatapointType[@SizeInBit = $grosse]" />
<xsl:variable name="master2" select="document('knx_master.xml')/b:KNX/b:MasterData/b:DatapointTypes/b:DatapointType/b:DatapointSubtypes/b:DatapointSubtype[@Id = current()/../@DatapointType]" />
<xsl:variable name="master3" select="document('knx_master.xml')/b:KNX/b:MasterData/b:DatapointTypes/b:DatapointType[@Id = current()/../@DatapointType]" />
<xsl:variable name="graddress" select="/b:KNX/b:Project/b:Installations/b:Installation/b:GroupAddresses/b:GroupRanges/b:GroupRange/b:GroupRange" />
<datapoint>     
    <xsl:attribute name="stateBased">
        <xsl:value-of select="'true'"/>
    </xsl:attribute>
    <xsl:attribute name="name">
        <xsl:value-of select="$verz/@Name"/>
    </xsl:attribute>
    <xsl:attribute name="mainNumber">
        <xsl:choose>
        <xsl:when test="../@DatapointType != ''">
            <xsl:choose>
            <xsl:when test="string-length(../@DatapointType) > 5">
                <xsl:value-of select="$master2/../../@Number"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$master3/@Number"/>
            </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$master/@Number"/>
        </xsl:otherwise>
        </xsl:choose>
    </xsl:attribute>
    <xsl:attribute name="dptID">
        <xsl:choose>
        <xsl:when test="../@DatapointType != ''">
            <xsl:choose>
            <xsl:when test="string-length(../@DatapointType) > 5">
                <xsl:value-of select="concat($master2/../../@Number, '.',format-number($master2/@Number, '000') )"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="concat($master3/@Number, '.001')"/>
            </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="concat($master/@Number,'.',format-number($master/b:DatapointSubtypes/b:DatapointSubtype/@Number, '000'))"/>
        </xsl:otherwise>
        </xsl:choose>
    </xsl:attribute>
    <xsl:attribute name="priority">
        <xsl:choose>
        <xsl:when test="../@Priority">
        <xsl:value-of select="../@Priority"/>
        </xsl:when>
        <xsl:otherwise>
        <xsl:value-of select="$verz/@Priority"/>
        </xsl:otherwise>
        </xsl:choose>
    </xsl:attribute>

    <xsl:for-each select="b:Send">
            <knxAddress type="group">
                <xsl:value-of select="$graddress/b:GroupAddress[@Id = current()/@GroupAddressRefId]/@Address"/>
            </knxAddress>
    </xsl:for-each>
    <expiration timeout="0"/>
        <xsl:choose>
        <xsl:when test="b:Receive">
            <xsl:for-each select="b:Receive">
                <updatingAddresses>
                    <xsl:value-of select="$graddress/b:GroupAddress[@Id = current()/@GroupAddressRefId]/@Address"/>
                </updatingAddresses>
            </xsl:for-each>
        </xsl:when>
        <xsl:otherwise>
            <updatingAddresses>
                <xsl:text> </xsl:text>
            </updatingAddresses>
        </xsl:otherwise>
        </xsl:choose>
    <invalidatingAddresses>
        <xsl:text> </xsl:text>
    </invalidatingAddresses>
</datapoint>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</datapoints>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

using Saxon 6.5.5. in a windows command line using this command:

java -jar C:\Saxon\Saxon6.5.5\saxon.jar -t -o calimero.xml 0.xml ets4_calimero_gui.xsl

The two files are in the correct directory and the output is the followed:

'SAXON 6.5.5 from Michael Kay
 Java version 1.6.0_31
 Loading com.icl.saxon.sort.Compare_d
 Preparation time: 225 milliseconds
 Processing file:/C:/Saxon/Saxon6.5.5
 Building tree for file:/C:/Saxon/Sax
 tree.TinyBuilder
 Tree built in 33 milliseconds
 Loading java.net.URI
 Execution time: 100 milliseconds'

But the created calimero.xml only includes the following line:

<?xml version="1.0" encoding="iso-8859-1"?>

Does anybody know the problem?

Thanks, Mike

2条回答
倾城 Initia
2楼-- · 2019-08-07 06:14

It's not related to your problem, though it is related to the fact that you seem to be fairly inexperienced in XSLT...

Firstly, if you are using Saxon then there really can't be any good reason for using XSLT 1.0. (Even less, "XSLT 1.1" which was an abandoned working draft that was never finished). You should move to a recent Saxon release (the current version is 9.4) and take advantage of all the benefits of using XSLT 2.0.

Secondly, even given the limitations of XSLT 1.0, this is really bad code:

(a) It's written completely monolithically - one template rule only

(b) it uses the preceding axis, which is very inefficient

(c) it uses xsl:attribute unnecessarily, which is very verbose

etc.

To give you a feel for the difference, the datapoint element and its attributes could be created like this (some of the improvements, but not all, depend on XSLT 2.0):

<datapoint 
    stateBased="true" 
    name="{$verz/@Name}"
    mainNumber="{if (../@DatapointType != '')
                 then if(string-length(../@DatapointType) gt 5)
                      then $master2/../../@Number
                      else $master3/@Number
                 else $master/@Number}"
    dptId="{if (../@DatapointType != '')
            then if (string-length(../@DatapointType) gt 5)
                 then concat($master2/../../@Number, '.',format-number($master2/@Number, '000')
                 else concat($master3/@Number, '.001')
            else concat($master/@Number,'.',format-number($master/b:DatapointSubtypes/b:DatapointSubtype/@Number, '000'))}"
    priority="{(../@Priority, $verz/@Priority)[1]}"

That's 51 lines of code down to 14, and it could come down further by moving the common code fragments into a function.

查看更多
Animai°情兽
3楼-- · 2019-08-07 06:24

Your XML input is in the xmlns:

xmlns="http://knx.org/xml/project/11"

Whereas your xslt is looking for

xmlns:b="http://knx.org/xml/project/10"

Looks like the schema version has been bumped up :)

查看更多
登录 后发表回答