我一直在努力根据优先级从相同节点的数组中选择正确的节点。
这是XML:
<?xml version="1.0" encoding="UTF-8"?>
<LandXML>
<CgPoints>
<CgPoint name="name1" oID="id1"></CgPoint>
<CgPoint name="name2" oID="id2"></CgPoint>
<CgPoint name="name3" oID="id1"></CgPoint>
<CgPoint name="name4" oID="id1"></CgPoint>
<CgPoint name="name5" oID="id2"></CgPoint>
<CgPoint name="name6" oID="id3"></CgPoint>
</CgPoints>
<Points>
<Point uniqueID="name1" class="medium" text="text1"></Point>
<Point uniqueID="name2" class="medium" text="text2"></Point>
<Point uniqueID="name3" class="high" text="text3"></Point>
<Point uniqueID="name4" class="low" text="text4"></Point>
<Point uniqueID="name5" class="low" text="text5"></Point>
<Point uniqueID="name6" class="medium" text="text6"></Point>
</Points>
</LandXML>
我想要做的是浏览CgPoints
元素并从节点获取所有oID
名称,当有相同的oID
名称时,只选择一个class
元素中的最高Points
属性。之后,我想将text
属性添加到提取的oID
名称。
输出如下:
id1,text3, <!-- this is the node with `name` attribute value `name3` -->
id2,text2,
id3,text6, <!-- this is the node with `name` attribute value `name2` -->
这是迄今为止我提出的xslt:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
<xsl:output method="text" indent="no" encoding="utf-8"/>
<xsl:variable name="fileExt" select="'txt'"/>
<!-- Comma separator -->
<xsl:variable name="separator" select="','"/>
<xsl:key name="keyHPoint" match="/LandXML/Points/Point" use="@uniqueID"/>
<xsl:template match="/">
<xsl:apply-templates select="/LandXML/CgPoints/CgPoint">
</xsl:apply-templates>
</xsl:template>
<xsl:template match="/LandXML/CgPoints/CgPoint">
<xsl:variable name="name" select="./@name"/>
<xsl:variable name="id" select="./@oID"/>
<xsl:variable name="allpoints" select="/LandXML/CgPoints/CgPoint[@oID = $id]"/>
<xsl:variable name="Point1" select="key('keyHPoint', $allpoints/@oID)"/>
<xsl:choose>
<xsl:when test="count($allpoints) = 1">
<xsl:value-of select="concat($id, $separator)"/>
<xsl:apply-templates select="/LandXML/Points/Point[@uniqueID = $name]"/>
<xsl:call-template name="newline">
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$Point1[@class = 'high']">
<xsl:value-of select="concat($id, $separator)"/>
<xsl:apply-templates select="/LandXML/Points/Point[@uniqueID = $name]"/>
<xsl:call-template name="newline">
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$Point1[@class = 'medium']">
<xsl:value-of select="concat($id, $separator)"/>
<xsl:apply-templates select="/LandXML/Points/Point[@uniqueID = $numurs]"/>
<xsl:call-template name="newline">
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:choose>
<xsl:when test="$Point1[@class = 'low']">
<xsl:value-of select="concat($id, $separator)"/>
<xsl:apply-templates select="/LandXML/Points/h:Point[@uniqueID = $name]"/>
<xsl:call-template name="newline">
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Text template -->
<xsl:template match="/LandXML/Points/Point">
<xsl:value-of select="concat(./@text, $separator)"/>
</xsl:template>
<!-- New line -->
<xsl:template name="newline">
<xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
使用此xslt,我获得所有节点的输出,不应用优先级选择。 在此先感谢您的帮助!
答案 0 :(得分:2)
使用XSLT 2或3,您可以按oID
属性进行分组,按引用的类对每个组进行排序(例如,通过在一系列可能的值中取index-of
)然后输出首先按排序顺序(https://xsltfiddle.liberty-development.net/nc4NzQj/1):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:param name="class-order" as="xs:string*" select="'high', 'medium', 'low'"/>
<xsl:output method="text"/>
<xsl:key name="pref" match="Point" use="@uniqueID"/>
<xsl:template match="/">
<xsl:for-each-group select="LandXML/CgPoints/CgPoint" group-by="@oID">
<xsl:for-each select="current-group()">
<xsl:sort select="index-of($class-order, key('pref', @name)/@class)"/>
<xsl:if test="position() eq 1">
<xsl:value-of select="current-grouping-key(), key('pref', @name)/@text" separator=","/>
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
使用XSLT 1,您可以以某种方式使用相同的算法,只有分组必须使用密钥和Muenchian分组以及排序,例如通过获取剩余类值的串联的字符串长度({{3} }):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="class-order" select="'high|medium|low'"/>
<xsl:output method="text"/>
<xsl:key name="point-group" match="CgPoint" use="@oID"/>
<xsl:key name="pref" match="Point" use="@uniqueID"/>
<xsl:template match="/">
<xsl:for-each select="LandXML/CgPoints/CgPoint[generate-id() = generate-id(key('point-group', @oID)[1])]">
<xsl:for-each select="key('point-group', @oID)">
<xsl:sort select="string-length(substring-after($class-order, key('pref', @name)/@class))" order="descending"/>
<xsl:if test="position() = 1">
<xsl:value-of select="concat(@oID, ',', key('pref', @name)/@text, ' ')"/>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>