XSLT:根据XML文件中缺少的属性省略节点/元素

时间:2017-01-20 19:21:40

标签: xml xslt xslt-1.0

我有一个XML文件,它是一个关于高速公路横截面点的报告。生成文件时,一些元素最多复制4次,但4个中只有1个包含“斜率”字段,这是我最终报告的关键字段。

我希望根据缺少的斜率属性排除这些节点/元素,但保留包含此属性的节点/元素。

**我的XML剪辑,带有正确形成的横截面点集:

-<CrossSectionStation longitudinalGrade="0.000000" elevation="0.000000" easting="342721.507535" northing="5048123.408983" radialDirection="1.267593" tangentialDirection="5.979982" rightOffset="10.562000" leftOffset="-9.597000" instantaneousRadius="1164.251000">

<Station externalStation="11699.999930" externalStationName="" internalStation="11699.999930"/>


-<CrossSectionSurfaces>


-<CrossSectionSurface type="1" name="Tehk_Design">


-<CrossSectionPoints>


-<CrossSectionPoint elevation="181.053000" easting="342715.470121" northing="5048121.520257" type="CrossSectionPoint" flag="Begin" offset="-6.325950">


-<CrossSectionFeatures>

<CrossSectionFeature name="LOS-Unpaved" aheadLongitudinalSlope="0.018811" description="Created by roadway design" style="Lawn" backLongitudinalSlope="0.015301"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.041488" length="1.399203" height="-0.058000" width="1.398000" averageCrossSlopeArea="92.467558"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="181.111000" easting="342716.804352" northing="5048121.937670" type="CrossSectionPoint" offset="-4.927950">


-<CrossSectionFeatures>

<CrossSectionFeature name="LOS" aheadLongitudinalSlope="0.019897" description="Created by roadway design" style="Shoulder" backLongitudinalSlope="0.015183"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.032086" length="1.683866" height="-0.054000" width="1.683000" averageCrossSlopeArea="96.359778"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="181.165000" easting="342718.410582" northing="5048122.440178" type="CrossSectionPoint" offset="-3.244950">


-<CrossSectionFeatures>

<CrossSectionFeature name="LEP" aheadLongitudinalSlope="0.019428" description="Created by roadway design" style="EOP" backLongitudinalSlope="0.015258"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="0.026132" length="3.246058" height="0.084797" width="3.244950"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="181.079000" easting="342721.551463" northing="5048123.422800" type="CrossSectionPoint" offset="0.046050">


-<CrossSectionFeatures>

<CrossSectionFeature name="CL" aheadLongitudinalSlope="0.018582" description="Created by roadway design" style="Centerline" backLongitudinalSlope="0.015160"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.026132" length="0.046066" height="-0.001203" width="0.046050"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="180.958000" easting="342724.776330" northing="5048124.431697" type="CrossSectionPoint" offset="3.425050">


-<CrossSectionFeatures>

<CrossSectionFeature name="REP" aheadLongitudinalSlope="0.018796" description="Created by roadway design" style="EOP" backLongitudinalSlope="0.014588"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.035809" length="3.381166" height="-0.121000" width="3.379000" averageCrossSlopeArea="192.331956"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="180.870000" easting="342726.297620" northing="5048124.907631" type="CrossSectionPoint" offset="5.019050">


-<CrossSectionFeatures>

<CrossSectionFeature name="ROS" aheadLongitudinalSlope="0.018099" description="Created by roadway design" style="Shoulder" backLongitudinalSlope="0.014358"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.055207" length="1.596427" height="-0.088000" width="1.594000" averageCrossSlopeArea="79.348793"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="180.761000" easting="342727.506826" northing="5048125.285930" type="CrossSectionPoint" offset="6.286050">


-<CrossSectionFeatures>

<CrossSectionFeature name="ROS-Unpaved" aheadLongitudinalSlope="0.019438" description="Created by roadway design" style="Lawn" backLongitudinalSlope="0.016869"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.086030" length="1.271680" height="-0.109000" width="1.267000" averageCrossSlopeArea="109.924454"/>

</CrossSectionPoint>

</CrossSectionPoints> 

**我的XML剪辑有多个重复要删除输出电子表格:

-<CrossSectionStation longitudinalGrade="0.000000" elevation="0.000000" easting="342678.439626" northing="5048318.465164" radialDirection="1.439378" tangentialDirection="6.151767" rightOffset="7.851000" leftOffset="-8.001000" instantaneousRadius="1164.251000">

<Station externalStation="11900.000000" externalStationName="" internalStation="11900.000000"/>


-<CrossSectionSurfaces>


-<CrossSectionSurface type="1" name="Tehk_Design">


-<CrossSectionPoints>


-<CrossSectionPoint elevation="184.686334" easting="342672.441830" northing="5048317.672373" type="CrossSectionPoint" flag="Begin" offset="-6.049965">


-<CrossSectionFeatures>

<CrossSectionFeature name="LOS-Unpaved" aheadLongitudinalSlope="0.016925" description="Created by roadway design" style="Lawn" backLongitudinalSlope="0.017052"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.116733" length="1.033989" height="-0.119886" width="1.027015"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.806546" easting="342673.462757" northing="5048317.807319" type="CrossSectionPoint" offset="-5.020158">


-<CrossSectionFeatures>

<CrossSectionFeature name="LOS" aheadLongitudinalSlope="0.016573" description="Created by roadway design" style="Shoulder" backLongitudinalSlope="0.017549"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.032671" length="1.787161" height="-0.058357" width="1.786208" averageCrossSlopeArea="90.739170"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.864903" easting="342675.233563" northing="5048318.041385" type="CrossSectionPoint" offset="-3.233950">


-<CrossSectionFeatures>

<CrossSectionFeature name="LEP" aheadLongitudinalSlope="0.016429" description="Created by roadway design" style="EOP" backLongitudinalSlope="0.018203"/>

</CrossSectionFeatures>

<CrossSectionSegment length="0.000317" height="-0.000010" width="0.000317" averageCrossSlopeArea="0.007925"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.864914" easting="342675.233877" northing="5048318.041427" type="CrossSectionPoint" offset="-3.233633">


-<CrossSectionFeatures>

<CrossSectionFeature name="LEP" aheadLongitudinalSlope="0.016429" description="Created by roadway design" style="EOP" backLongitudinalSlope="0.018203"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="0.030621" length="3.235149" height="0.099016" width="3.233633"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.763633" easting="342678.512952" northing="5048318.474856" type="CrossSectionPoint" offset="0.073963">


-<CrossSectionFeatures>

<CrossSectionFeature name="CL" aheadLongitudinalSlope="0.016771" description="Created by roadway design" style="Centerline" backLongitudinalSlope="0.018281"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.030621" length="0.073998" height="-0.002265" width="0.073963"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.763630" easting="342678.513038" northing="5048318.474868" type="CrossSectionPoint" offset="0.074050">


-<CrossSectionFeatures>

<CrossSectionFeature name="CL" aheadLongitudinalSlope="0.016771" description="Created by roadway design" style="Centerline" backLongitudinalSlope="0.018281"/>

</CrossSectionFeatures>

<CrossSectionSegment length="0.000087" height="-0.000003" width="0.000087" averageCrossSlopeArea="0.002174"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.661095" easting="342681.820271" northing="5048318.912020" type="CrossSectionPoint" offset="3.410050">


-<CrossSectionFeatures>

<CrossSectionFeature name="REP" aheadLongitudinalSlope="0.016450" description="Created by roadway design" style="EOP" backLongitudinalSlope="0.018392"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.030736" length="3.337575" height="-0.102535" width="3.336000" averageCrossSlopeArea="167.476560"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.661073" easting="342681.820984" northing="5048318.912114" type="CrossSectionPoint" offset="3.410768">


-<CrossSectionFeatures>

<CrossSectionFeature name="REP" aheadLongitudinalSlope="0.016450" description="Created by roadway design" style="EOP" backLongitudinalSlope="0.018392"/>

</CrossSectionFeatures>

<CrossSectionSegment length="0.000719" height="-0.000022" width="0.000718" averageCrossSlopeArea="0.017969"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.567875" easting="342683.404492" northing="5048319.121423" type="CrossSectionPoint" offset="5.008050">


-<CrossSectionFeatures>

<CrossSectionFeature name="ROS" aheadLongitudinalSlope="0.017219" description="Created by roadway design" style="Shoulder" backLongitudinalSlope="0.018264"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.058348" length="1.599998" height="-0.093199" width="1.597282" averageCrossSlopeArea="78.130412"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.567856" easting="342683.404816" northing="5048319.121466" type="CrossSectionPoint" offset="5.008377">


-<CrossSectionFeatures>

<CrossSectionFeature name="ROS" aheadLongitudinalSlope="0.017219" description="Created by roadway design" style="Shoulder" backLongitudinalSlope="0.018264"/>

</CrossSectionFeatures>

<CrossSectionSegment length="0.000328" height="-0.000019" width="0.000327" averageCrossSlopeArea="0.008192"/>

</CrossSectionPoint>


-<CrossSectionPoint elevation="184.474567" easting="342684.250248" northing="5048319.233215" type="CrossSectionPoint" offset="5.861162">


-<CrossSectionFeatures>

<CrossSectionFeature name="ROS-Unpaved" aheadLongitudinalSlope="0.018074" description="Created by roadway design" style="Lawn" backLongitudinalSlope="0.017443"/>

</CrossSectionFeatures>

<CrossSectionSegment slope="-0.109393" length="0.001119" height="-0.000122" width="0.001112"/>

</CrossSectionPoint>

</CrossSectionPoints>

**我修改过的XSL,即正确格式化所有内容但不删除重复项:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:inr="http://mycompany.com/mynamespace">
    <xsl:include href="../format.xsl"/>
    <xsl:param name="xslRootDirectory" select="inr:xslRootDirectory"/>
    <!-- Unique cross section surfaces -->
    <xsl:variable name="uniqueSurfaceName" select="//CrossSectionSurfaces/CrossSectionSurface[not (@name = preceding::CrossSectionSurface/@name)]/@name"/>
    <!-- Slope Stake Listing -->
    <xsl:template match="/">
        <xsl:variable name="gridOut" select="inr:SetGridOut(number(InRoads/@outputGridScaleFactor))"/>
        <html>
            <head>
                <link rel="stylesheet" type="text/css" href="{$xslRootDirectory}/_Themes/engineer/document.css"/>
                <!-- Title displayed in browser Title Bar -->
                <title lang="en">Slope Stake Listing</title>
            </head>
            <body>
                <xsl:choose>
                    <xsl:when test="$xslShowHelp = 'true'">
                        <xsl:call-template name="StyleSheetHelp"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:for-each select="InRoads">
                            <center>
                                <!-- Report Title -->
                                <h6 lang="en">SLOPE STAKE LISTING</h6>
                                <p lang="en">
                                    <xsl:value-of select="inr:longDate()"/>&#xa0; <xsl:value-of select="inr:longTime()"/>
                                </p>
                            </center>
                            <!-- Cross Section Set Data -->
                            <xsl:for-each select="CrossSectionSet">
                                <table class="margin">
                                    <tbody>
                                        <tr>
                                            <td lang="en">Set Name:&#xa0; </td>
                                            <td><xsl:value-of select="@setName"/></td>
                                        </tr>
                                        <tr>
                                            <td lang="en">Project Units:&#xa0; </td>
                                            <td lang="en">
                                                <xsl:if test="//@linearUnits = 'Imperial'">US Survey Feet</xsl:if>
                                                <xsl:if test="//@linearUnits = 'Metric'">Metric</xsl:if>
                                            </td>
                                        </tr>
                                        <tr>
                                            <td lang="en">Contract No.:&#xa0; </td>
                                            <td>&#xa0;</td>
                                        </tr>
                                        <tr>
                                            <td lang="en">Co./Rte./PM:&#xa0; </td>
                                            <td>&#xa0;</td>
                                        </tr>
                                    </tbody>
                                </table>
                                <hr/>
                                <!-- Cross Section Point Data -->
                                <table class="margin" width="90%">
                                    <xsl:for-each select="$uniqueSurfaceName[../@type = 1]">
                                        <xsl:for-each select="//CrossSectionSurface[@name = current()]">
                                            <xsl:for-each select="CrossSectionPoints">
                                                <!-- Alignment Name -->
                                                <tr>
                                                    <th colspan="11" lang="en">
                                                        Alignment Chain:&#xa0; <xsl:value-of select="../../../../../@alignmentName"/>
                                                    </th>
                                                </tr>
                                                <!-- Station -->
                                                <tr>
                                                    <th colspan="11" lang="en">
                                                        Station:&#xa0; <xsl:value-of select="inr:stationFormat(number(../../../Station/@externalStation), $xslStationFormat,$xslStationPrecision, string(../../../Station/@externalStationName))"/>
                                                    </th>
                                                </tr>
                                                <!-- Feature Name -->
                                                <tr>
                                                    <xsl:for-each select="CrossSectionPoint[position() = 1][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <th>CP</th>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[CrossSectionFeatures/CrossSectionFeature/@name] | CrossSectionPoint[not (CrossSectionFeatures/CrossSectionFeature/@name) and (@offset &gt; -0.0001 and @offset &lt; 0.0001)]">
                                                        <th>
                                                            <xsl:value-of select="CrossSectionFeatures/CrossSectionFeature/@name"/>
                                                        </th>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[position() = last()][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <th>CP</th>
                                                    </xsl:for-each>
                                                </tr>
                                                <!-- Offset -->
                                                <tr>
                                                    <xsl:for-each select="CrossSectionPoint[position() = 1][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:distanceFormat(number(@offset), $xslDistancePrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[CrossSectionFeatures/CrossSectionFeature/@name] | CrossSectionPoint[not (CrossSectionFeatures/CrossSectionFeature/@name) and (@offset &gt; -0.0001 and @offset &lt; 0.0001)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:distanceFormat(number(@offset), $xslDistancePrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[position() = last()][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:distanceFormat(number(@offset), $xslDistancePrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                </tr>
                                                <!-- Elevation -->
                                                <tr>
                                                    <xsl:for-each select="CrossSectionPoint[position() = 1][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:elevationFormat(number(@elevation), $xslElevationPrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[CrossSectionFeatures/CrossSectionFeature/@name] | CrossSectionPoint[@offset &gt; -0.0001 and @offset &lt; 0.0001]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:elevationFormat(number(@elevation), $xslElevationPrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[position() = last()][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:elevationFormat(number(@elevation), $xslElevationPrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                </tr>
                                                <!-- Slope -->
                                                <tr>
                                                    <xsl:for-each select="CrossSectionPoint[position() = 1][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:alternateGradeFormat(number(CrossSectionSegment/@slope), $xslGradeFormat, $xslGradePrecision, $xslIfSlopeExceeds, $xslAlternateSlopeFormat, $xslAlternateSlopePrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[CrossSectionFeatures/CrossSectionFeature/@name] | CrossSectionPoint[not (CrossSectionFeatures/CrossSectionFeature/@name) and (@offset &gt; -0.0001 and @offset &lt; 0.0001)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:alternateGradeFormat(number(CrossSectionSegment/@slope), $xslGradeFormat, $xslGradePrecision, $xslIfSlopeExceeds, $xslAlternateSlopeFormat, $xslAlternateSlopePrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                    <xsl:for-each select="CrossSectionPoint[position() = last()][not (CrossSectionFeatures/CrossSectionFeature/@name)]">
                                                        <td align="center" style="padding-left:5px;padding-right:5px;white-space:nowrap;">
                                                            <xsl:value-of select="inr:alternateGradeFormat(number(CrossSectionSegment/@slope), $xslGradeFormat, $xslGradePrecision, $xslIfSlopeExceeds, $xslAlternateSlopeFormat, $xslAlternateSlopePrecision)"/>
                                                        </td>
                                                    </xsl:for-each>
                                                </tr>                                             
                                                <tr><td>&#xa0;</td></tr>
                                            </xsl:for-each>
                                        </xsl:for-each>
                                    </xsl:for-each>
                                </table>
                            </xsl:for-each>
                        </xsl:for-each>
                    </xsl:otherwise>
                </xsl:choose>
            </body>
        </html>
    </xsl:template>
</xsl:stylesheet>

这就是XML的第一部分生成的内容,这就是我希望它们看起来像的样子:

输出图像: Proper Layout Improper Layout

如果您需要更多信息,请提前告知我们。

1 个答案:

答案 0 :(得分:2)

为了简化说明,我们省略HTML并只留下XSLT。

你写道 LOS-Omitted LOS-Retained 分别被省略和保留。

这意味着您对属性(name)遇到的源数据感兴趣 特殊条件(其值为LOS-Retained)。

这种情况可表示为:

<xsl:for-each select=
     "CrossSectionPoint[CrossSectionFeatures/CrossSectionFeature/@name = 'LOS-Retained']"/>

但如果您对此属性缺失的元素感兴趣, 你应该写道:

<xsl:for-each select=
     "CrossSectionPoint[not(CrossSectionFeatures/CrossSectionFeature/@name)]"/>

如果您对两者感兴趣,请写下:

<xsl:for-each select=
    "CrossSectionPoint[CrossSectionFeatures/CrossSectionFeature/@name = 'LOS-Retained']
    | CrossSectionPoint[not(CrossSectionFeatures/CrossSectionFeature/@name)]">

在您的XSLT中找到相应的位置,然后添加缺少的= 'LOS-Retained'

我在你的例子中看到,第二个子条件(&#34; |&#34;之后)也包括and @offset = 0.0

正如你&#34;继承&#34;这个XSLT在别人之后,你必须决定是留下这个片段还是丢弃它。

如果您决定离开,请将0.0更改为'0.0'(用引号括起来)。

属性值读取为字符串,XSLT代码为&#34; clean&#34;在这种比较中使用字符串值时。

编辑2017-01-27的评论

在你的评论中你写道:

  

...过滤掉&#34; CrossSectionPoints&#34;不包含的   &#34; CrossSectionSegment&#34;斜率值

我想你的意图是

  

...过滤掉每个&#34; CrossSectionPoint&#34;那...

(注意缺少&#34; s&#34;)。

假设当前节点是CrossSectionPoint,表达此条件的谓词为:[not(CrossSectionSegment/@slope)]

您必须决定如何将此谓词与您for-each循环中已存在的谓词连接起来 (围绕<td align="center">)。