【问题标题】:XSL to create folders based on attributeXSL 基于属性创建文件夹
【发布时间】:2011-06-14 16:21:31
【问题描述】:

我正在使用 XSL 将 XML 转换为 KML,以便在 Google 地球中查看。我将能够在下面的 XML 示例中为每个“IT_Type”创建文件夹

目前,XML 正在被转换成这样的文件夹结构:

    • VSS1
    • VSS2
    • 驾驶室1
    • 驾驶室2
    • DMS1
    • DMS2
  • 线路
    • 发件人:收件人:
    • 发件人:收件人:
    • 发件人:收件人:

它需要被构造成这样的文件夹,在 Point 和 Line 父文件夹下为每个 IT_Type 设置一个文件夹。

    • VSS
      • VSS1
      • VSS2
    • 机柜
      • 驾驶室1
      • 驾驶室2
    • DMS
      • DMS1
      • DMS2
  • 线路
    • 手孔
      • 发件人:收件人:
    • 机柜
      • 发件人:收件人:
    • 其他
      • 发件人:收件人:

为此设置 XSL 的最佳方法是什么?性能是否会成为大型数据集的问题?

感谢任何建议或代码示例。

谢谢。

请参阅下面的示例 XML

<Parents>
  <Point>
    <Row IT_ID="116" IT_Name="VSS1" IT_Type="VSS" GPSLat="43.953000000000" GPSLong="-85.671800000000" />
    <Row IT_ID="117" IT_Name="VSS2" IT_Type="VSS" GPSLat="43.966900000000" GPSLong="-85.678900000000" />
    <Row IT_ID="122" IT_Name="Cab1" IT_Type="Cabinet" GPSLat="43.903100000000" GPSLong="-85.677100000000" />
    <Row IT_ID="123" IT_Name="Cab2" IT_Type="Cabinet" GPSLat="43.913500000000" GPSLong="-85.677300000000" />
    <Row IT_ID="254" IT_Name="DMS1" IT_Type="DMS" GPSLat="43.903100000000" GPSLong="-85.677100000000" />
    <Row IT_ID="255" IT_Name="DMS2" IT_Type="DMS" GPSLat="43.989400000000" GPSLong="-85.676800000000" />
  </Point>
  <Line>
    <Row LINE_ID="1117" IT_Type="Handhole" FROM_SYSTEM_ID="2127" TO_SYSTEM_ID="1947" FromLat="43.438474034300" FromLong="-83.195331982500" ToLat="43.437072542900" ToLong="-83.193657308800">
      <Row2 LINE_ID="1117" CONDUIT_NUMBER="1" CONDUIT_TYPE="Fiber" FIBER_NUMBER="1" FIBER_TYPE="Trunk" STRANDS="96" />
      <Row2 LINE_ID="1117" CONDUIT_NUMBER="2" CONDUIT_TYPE="Empty" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" />
      <Row2 LINE_ID="1117" CONDUIT_NUMBER="3" CONDUIT_TYPE="Empty" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" />
      <Row2 LINE_ID="1117" CONDUIT_NUMBER="4" CONDUIT_TYPE="Empty" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" />
    </Row>
    <Row LINE_ID="997" IT_Type="Cabinet" FROM_SYSTEM_ID="2011" TO_SYSTEM_ID="2012" FromLat="43.482705558800" FromLong="-83.260130135400" ToLat="43.482694479700" ToLong="-83.260107590500">
      <Row2 LINE_ID="997" CONDUIT_NUMBER="1" CONDUIT_TYPE="Other" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" />
    </Row>
    <Row LINE_ID="1220" IT_Type="Other" FROM_SYSTEM_ID="2415" TO_SYSTEM_ID="2413" FromLat="43.624664303600" FromLong="-83.086848805700" ToLat="43.624645615600" ToLong="-83.086770805500">
      <Row2 LINE_ID="1220" CONDUIT_NUMBER="1" CONDUIT_TYPE="Fiber" FIBER_NUMBER="1" FIBER_TYPE="Dist" STRANDS="12" />
      <Row2 LINE_ID="1220" CONDUIT_NUMBER="2" CONDUIT_TYPE="Electric" FIBER_NUMBER="" FIBER_TYPE="" STRANDS="" />
    </Row>
  </Line>
</Parents>

请参阅下面的我的 XSL:

<xsl:template match="Parents">
  <Folder>
    <name>
      Point
    </name>
    <xsl:for-each select="Point/Row">
      <Placemark>
        <name>
          <xsl:value-of select="@IT_Name"/>
        </name>
        <description>
          <xsl:value-of select="@Location"/>
        </description>
        <styleUrl>
          <xsl:value-of select="concat($hash,@IT_Type)"/>
        </styleUrl>
        <Point>
          <coordinates>
            <xsl:value-of select="@GPSLong"/>,
            <xsl:value-of select="@GPSLat"/>
          </coordinates>
        </Point>
      </Placemark>
    </xsl:for-each>
  </Folder>
  <Folder>
    <name>
      Line
    </name>
    <xsl:for-each select="Line/Row">
      <Placemark>
        <name>
          From: <xsl:value-of select="@FROM_SYSTEM_ID"/> to: <xsl:value-of select="@TO_SYSTEM_ID"/>
        </name>
        <description>
          <xsl:value-of select="@CONDUIT_NUMBER"/>
        </description>
        <styleUrl>
          <xsl:value-of select="concat($hash,@IT_Type)"/>
        </styleUrl>
        <LineString>
          <tessellate>1</tessellate>
          <coordinates>
            <xsl:value-of select="@FromLong"/>,<xsl:value-of select="@FromLat"/>,0 <xsl:value-of select="@ToLong"/>,<xsl:value-of select="@ToLat"/>,0
          </coordinates>
        </LineString>
      </Placemark>
    </xsl:for-each>
  </Folder>
</xsl:template>

【问题讨论】:

  • 好问题 (+1)。我已经从您的模板中扣除了目标结果树片段。下次也请提供一个有意义的所需输出样本。

标签: xslt


【解决方案1】:

很抱歉完全修改了您的初始模板,但执行此操作的常用方法(在 XSLT 1.0 中)是将 Meunchian 的方法应用于多级分组。在您的特定情况下,您可以基于@IT_TypeRow 的父元素的串联创建xsl:key


例如,这个 XSLT 1.0(在 Saxon 6.5 下测试)

<xsl:stylesheet 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:key name="kIT_Type" 
        match="Row" 
        use="concat(
        name(parent::node()),@IT_Type
        )"/>


    <xsl:template match="Parents/*">
        <Folder>
            <name><xsl:value-of select="name()"/></name>
            <xsl:apply-templates select="Row[
                generate-id(.) 
                = 
                generate-id(key('kIT_Type',
                concat(name(parent::node()),@IT_Type))[1])
                    ]"/>
        </Folder>
    </xsl:template>

<xsl:template match="Row">
    <Folder>
        <name><xsl:value-of select="@IT_Type"/></name>
        <xsl:apply-templates select="key('kIT_Type',
            concat(name(parent::node()),@IT_Type))" 
            mode="placemark"/>
    </Folder>
</xsl:template>

    <xsl:template match="Row[parent::Point]" mode="placemark">
        <Placemark>
            <name>
                <xsl:value-of select="@IT_Name"/>
            </name>
            <description>
                <!--xsl:value-of select="@Location"/-->
            </description>
            <styleUrl>
                <!--xsl:value-of select="concat($hash,@IT_Type)"/-->
            </styleUrl>
            <Point>
                <coordinates>
                    <xsl:value-of select="@GPSLong"/>,
                    <xsl:value-of select="@GPSLat"/>
                </coordinates>
            </Point>
        </Placemark>
    </xsl:template>

    <xsl:template match="Row[parent::Line]" mode="placemark">
        <Placemark>
            <name>
                From: <xsl:value-of select="@FROM_SYSTEM_ID"/> to: <xsl:value-of select="@TO_SYSTEM_ID"/>
            </name>
            <description>
                <xsl:value-of select="@CONDUIT_NUMBER"/>
            </description>
            <styleUrl>
                <!-- xsl:value-of select="concat($hash,@IT_Type)"/-->
            </styleUrl>
            <LineString>
                <tessellate>1</tessellate>
                <coordinates>
                    <xsl:value-of select="@FromLong"/>,<xsl:value-of select="@FromLat"/>,0 <xsl:value-of select="@ToLong"/>,<xsl:value-of select="@ToLat"/>,0
                </coordinates>
            </LineString>
        </Placemark>
    </xsl:template>

    <xsl:template match="Row2"/>

</xsl:stylesheet>

应用于您的输入,生成 RTF:

<Folder>
   <name>Point</name>
   <Folder>
      <name>VSS</name>
      <Placemark>
         <name>VSS1</name>
         <description/>
         <styleUrl/>
         <Point>
            <coordinates>-85.671800000000,
                    43.953000000000</coordinates>
         </Point>
      </Placemark>
      <Placemark>
         <name>VSS2</name>
         <description/>
         <styleUrl/>
         <Point>
            <coordinates>-85.678900000000,
                    43.966900000000</coordinates>
         </Point>
      </Placemark>
   </Folder>
   <Folder>
      <name>Cabinet</name>
      <Placemark>
         <name>Cab1</name>
         <description/>
         <styleUrl/>
         <Point>
            <coordinates>-85.677100000000,
                    43.903100000000</coordinates>
         </Point>
      </Placemark>
      <Placemark>
         <name>Cab2</name>
         <description/>
         <styleUrl/>
         <Point>
            <coordinates>-85.677300000000,
                    43.913500000000</coordinates>
         </Point>
      </Placemark>
   </Folder>
   <Folder>
      <name>DMS</name>
      <Placemark>
         <name>DMS1</name>
         <description/>
         <styleUrl/>
         <Point>
            <coordinates>-85.677100000000,
                    43.903100000000</coordinates>
         </Point>
      </Placemark>
      <Placemark>
         <name>DMS2</name>
         <description/>
         <styleUrl/>
         <Point>
            <coordinates>-85.676800000000,
                    43.989400000000</coordinates>
         </Point>
      </Placemark>
   </Folder>
</Folder>
<Folder>
   <name>Line</name>
   <Folder>
      <name>Handhole</name>
      <Placemark>
         <name>
                From: 2127 to: 1947</name>
         <description/>
         <styleUrl/>
         <LineString>
            <tessellate>1</tessellate>
            <coordinates>-83.195331982500,43.438474034300,0 -83.193657308800,43.437072542900,0
                </coordinates>
         </LineString>
      </Placemark>
   </Folder>
   <Folder>
      <name>Cabinet</name>
      <Placemark>
         <name>
                From: 2011 to: 2012</name>
         <description/>
         <styleUrl/>
         <LineString>
            <tessellate>1</tessellate>
            <coordinates>-83.260130135400,43.482705558800,0 -83.260107590500,43.482694479700,0
                </coordinates>
         </LineString>
      </Placemark>
   </Folder>
   <Folder>
      <name>Other</name>
      <Placemark>
         <name>
                From: 2415 to: 2413</name>
         <description/>
         <styleUrl/>
         <LineString>
            <tessellate>1</tessellate>
            <coordinates>-83.086848805700,43.624664303600,0 -83.086770805500,43.624645615600,0
                </coordinates>
         </LineString>
      </Placemark>
   </Folder>
</Folder>

【讨论】:

  • 感谢您的回答,我从这种方法中学到了很多东西。我仍然需要能够将每个 IT_Type 组织到一个文件夹中,例如,Point(文件夹)> VSS(文件夹)> VSS1、VSS2 等。这可能吗?再次感谢您的帮助并重新编写 xsl
  • 谢谢!我现在正在查看 GE 的输出,它是完美的。非常感谢您的帮助,现在要重做很多旧代码...
猜你喜欢
  • 2018-09-26
  • 2012-05-09
  • 1970-01-01
  • 2023-04-02
  • 2012-02-11
  • 1970-01-01
  • 2018-10-01
  • 2015-07-25
  • 2017-11-29
相关资源
最近更新 更多