XSLT:尝试根据这两个节点的元素值组合两个节点

XSLT: Trying to combine two nodes based on the value of an element of those two nodes

我一直在为 XSLT 苦苦挣扎,已经好几天了。我正在修改以前的同事 python 代码,该代码将许多不同的 JSON 文件转换为 xml,最后转换为 kml。我差点把它包起来,当然,我无法理解的部分就是剩下的部分。

我有一个具有这种结构的 xml 文件:

    <?xml version="1.0" ?>
    <document xmlns="http://ws.wso2.org/dataservice">
        <group>
            <display_name>Housing</display_name>
            <id>Housing</id>
            <item>
                <id>5063</id>
                <image_url>images/5063.jpg</image_url>
                <latitude>40.354007</latitude>
                <longitude>-74.666675</longitude>
                <name>Stanworth Apartments</name>
            </item>
         .
         . (Many items omitted)
         .
    </group>
    <group>
        <display_name>Buildings</display_name>
        <id>Building</id>
        <item>
            <id>5025</id>
            <image_url>images/5025.jpg</image_url>
            <latitude>40.350066</latitude>
            <longitude>-74.603464</longitude>
            <name>Lyman Spitzer Building</name>
            <name_alt>LSB</name_alt>
            <organization_id>ORG418</organization_id>
        </item>
         .
         . (Many items omitted)
         .
    </group>
    <group>
         .
         . (Many groups omitted)
         .
    </group>
    <group>
        <display_name>Accessible Features</display_name>
        <id>Entryway</id>
        <item>
            <description>Accessible entryway</description>
            <id>E028</id>
            <latitude>40.349159</latitude>
            <longitude>-74.658629</longitude>
            <name>E028</name>
        </item>
        <item>
            <description>Accessible entryway</description>
            <id>E029</id>
            <latitude>40.349398</latitude>
            <longitude>-74.658517</longitude>
            <name>E029</name>
        </item>
    </group>
    <group>
        <display_name>Accessible Features</display_name>
        <id>Route</id>
        <item>
            <description>Accessible pathway</description>
            <id>R054</id>
            <name>R054</name>
            <steps>-74.66032495749012,40.3489269473544</steps>
            <steps>-74.6602836233495,40.34888813533125</steps>
        </item>
        <item>
            <description>Accessible pathway</description>
            <id>R055</id>
            <name>R055</name>
            <steps>-74.66023036637355,40.34884827131961</steps>
            <steps>-74.66018651597699,40.34881015960344</steps>
        </item>
        <item>
            <description>Accessible pathway</description>
            <id>R072</id>
            <name>R072</name>
            <steps>-74.66101885775542,40.34737535360176</steps>
            <steps>-74.6610915120654,40.34740600913134</steps>
            <steps>-74.66187000551304,40.34717392492537</steps>
        </item>
   </group>
</document>

在最终的 KML 文件中,每个“组”都转换为一个文件夹。

<Folder id="Housing">
    <name>Housing</name>
    <Placemark id="_0288">
          .
          . (Many lines omitted)
          .

目标是创建一个包含两组内容的文件夹“id='Accessible”。 id='Entryway'的组和id='Route.所需的输出将是:

<Folder id="Accessible">
    <name>Accessible Features</name>
    <Placemark id="_E001">
        <name>E001</name>
        <description><![CDATA[<div><p>Accessible entryway</p></div>]]></description>
        <styleUrl>#entryway</styleUrl>
        <Point>
            <coordinates>-74.663266, 40.348289,0</coordinates>
        </Point>
    </Placemark>
    <Placemark id="_E002">
        <name>E002</name>
        <description><![CDATA[<div><p>Accessible entryway</p></div>]]></description>
        <styleUrl>#entryway</styleUrl>
        <Point>
            <coordinates>-74.662252, 40.348057,0</coordinates>
        </Point>
    </Placemark>
      .
      . then have the items from the group with id='Route'
      .
     <Placemark id="_R002">
        <name>Accessible Routes</name>
        <description><![CDATA[<div><p>Accessible pathway</p></div>]]></description>
        <styleUrl/>
        <Style>
            <LineStyle>
                <color>FFFF0000</color>
                <width>4</width>
            </LineStyle>
        </Style>
        <LineString>
            <coordinates>
                      -74.65135187837255,40.34699608960065
                      -74.65134698312161,40.34698651192196
            </coordinates>
        </LineString>
    </Placemark>
     <Placemark id="_R003">
        <name>Accessible Routes</name>
        <description><![CDATA[<div><p>Accessible pathway</p></div>]]></description>
        <styleUrl/>
        <Style>
            <LineStyle>
                <color>FFFF0000</color>
                <width>4</width>
            </LineStyle>
        </Style>
        <LineString>
            <coordinates>
                      -74.65135184561255,40.34699603789065
                      -74.65134698312256 44.34698634192100
            </coordinates>
        </LineString>
    </Placemark>
      .
      . more than 66,000 lines omitted
      .
</Folder>

我已经编写了 XSLT 以将 XML 转换为这些 KML 文件夹,唯一剩下要做的就是将它们放在同一文件夹下。

我一直在尝试做的是将所有项目从 id='Route' 的组移动到 id='Entryway 的组。

在我的 xslt 文件中有一个组节点应用模板。

    <xsl:apply-templates select="ds:group">
        <xsl:sort select="ds:display_name"/>
    </xsl:apply-templates>

这是由每个组的模板匹配得到的。

<xsl:template match="ds:group">

此时我迷路了。我会 post 我的代码,但这只会让你感到困惑和沮丧。

<xsl:template match="ds:group">
    <xsl:choose>
        <xsl:when test="not(ds:id = 'Route') and not(ds:id = 'Entryway')">
            <Folder id="{ds:id}">
                <name>
                    <xsl:value-of select="ds:display_name"/>
                </name>
                <xsl:apply-templates select="ds:item">
                    <xsl:sort select="ds:name"/>
                </xsl:apply-templates>
            </Folder>
        </xsl:when>
        <xsl:when test="ds:id = 'Entryway'">
            <Folder id='Accessible'>
                <name>
                    <xsl:value-of select="ds:display_name"/>
                </name>
                <xsl:apply-templates select="ds:item">
                    <xsl:sort select="ds:name"/>
                </xsl:apply-templates>
            </Folder>
        </xsl:when>
        <xsl:when test="ds:id = 'Route'">
            <!--  Copy all of current node to Entryway node -->
        </xsl:when>
        <xsl:otherwise>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

我认为我的处理方式不正确。当 XSLT 进程到达 id='Route' 的组时,Entryway 的 KML 文件夹已经写入。我走投无路了。我可以根据“id”的值将两个组合并在一起吗?从概念上讲,这个想法是:<xsl:template match="ds:id='Route' | ds:id='Entryway'"> 但这甚至无法编译。

是否可以在处理完第一个组后将组(id='Route')的所有元素复制到组(id='Entryway')中?

提前感谢您的时间和关注。

乔治

我认为您需要在 document 级别“介入”并执行例如

<xsl:template match="ds:document">
  <Folder id='Accessible'>
    <xsl:apply-templates select="ds:group[ds:id = 'Entryway' or ds:id = 'Route']"/>
  </Folder>
  <!-- process other ds:group here as well e.g. 
       <xsl:apply-templates select="ds:group[not(ds:id = 'Entryway' or ds:id = 'Route')]"/>
  -->
</xsl:template>

AFAICT 你想做这样的事情:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ns0="http://ws.wso2.org/dataservice"
exclude-result-prefixes="ns0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/ns0:document">
    <Folders>
        <xsl:variable name="accessible" select="ns0:group[ns0:id='Entryway' or ns0:id ='Route']" />
        <xsl:if test="$accessible">
            <Folder id="Accessible">
                <name>Accessible Features</name>
                <xsl:apply-templates select="$accessible/ns0:item"/>
            </Folder>
        </xsl:if>
        <xsl:apply-templates select="ns0:group[not(ns0:id='Entryway' or ns0:id ='Route')]"/>
    </Folders>
</xsl:template>

<xsl:template match="ns0:group">
    <Folder id="{ns0:id}">
        <name>
            <xsl:value-of select="display_name"/>
        </name>
        <xsl:apply-templates select="ns0:item"/>
    </Folder>
</xsl:template>

<xsl:template match="ns0:item">
    <Placemark id="{ns0:id}">
        <name>
            <xsl:value-of select="ns0:name"/>
        </name>
        <!-- more here -->
    </Placemark>
</xsl:template>

</xsl:stylesheet>
<xsl:template match="/ds:document">
    <kml>
        <Document>
            <name>Campus Map</name>                
            <xsl:apply-templates select="ds:group[ds:id != 'Entryway' and ds:id != 'Route']">
                <xsl:sort select="ds:display_name"/>
            </xsl:apply-templates>
            <Folder id='Accessible'>
                <name>Accessible Feature</name>
                    <xsl:apply-templates select="ds:group[ds:id = 'Entryway' or ds:id = 'Route']"/>
            </Folder>
        </Document>
    </kml>
</xsl:template>
    
<xsl:template match="ds:group[ds:id = 'Entryway' or ds:id = 'Route']">
    <xsl:apply-templates select="ds:item"/>
</xsl:template>
    
<xsl:template match="ds:group[ds:id != 'Entryway' and ds:id != 'Route']">
    <Folder id="{ds:id}">
        <name>
            <xsl:value-of select="ds:display_name"/>
        </name>
        <xsl:apply-templates select="ds:item">
            <xsl:sort select="ds:name"/>
        </xsl:apply-templates>
    </Folder>
</xsl:template>