基于XSLT实现XML元素及属性的字母序排序需求
XML元素与属性按字母排序的XSLT实现
需求说明
我需要将XML文件中的元素以及元素内的属性都按字母顺序排序,目前刚接触XSLT,尝试写了模板但没达到预期效果。
源XML(source.xml)
<?xml version="1.0" encoding="UTF-8"?> <wgtPage projectType="project" rev="1"> <object staticFile="opt/IMAGE.png" id="ZZZZZZZZZ" staticOptEnable="true" dataWndSize="0,70" downloadPrepDone="true" usedFonts="Siemens AD Sans" pageSize="1920,1080" class="PageWgt" pageName="PAGENAME" templateFile="PAEGEFILE.XML"> <wgtStyle width="1920" height="1080" ver="040500548" fitToSize="1" x="0" y="0" v="04.05.00.548"/> <object mgrType="Page" id="_PageMLTextMgrWgt" mlFileName="" class="PageMLTextMgrWgt"> <wgtStyle width="0" height="0" x="0" y="0"/> <langs curLangId="L1" defLangId="L1"> <lang name="ITA" defaultFont="ARIAL" keypads=";;;" writingsystem="Any" langId="L1" langCode="it" removable="false"/> </langs> <MLTexts> <MLText id="0" L1="A"/> <MLText id="1" L1="E "/> <MLText id="36" L1="D"/> <MLText id="37" L1="B"/> </MLTexts> </object> <object id="label11" class="LabelWgt"> <wgtStyle wrapping="true" width="247" height="29" font-bold="true" keypad-type="None" vert-align="middle" font-sizepx="21" font-color="rgb(255,215,0)" font-size="16" marker="true" x="9" y="28" forcePaint="1" cx="123.50" cy="13.74" font-family="Sans"/> <links> <lang textid="0" class="MLTextLink"/> </links> </object> <links> <lang textid="36" class="MLTextLink"/> </links> </object> <object id="GroupWgt5.label1" class="LabelWgt"> <wgtStyle y="877" font-size="22" height="76" frameSize="0" vert-align="middle" font-family="ARIAL" x="1122" alignment="center" forcePaint="25" wgtStaticOpt="dynamic" frameColor="rgb(200,200,200)" font-color="rgb(255,255,255)" cy="34.20" frameFill="rgb(102,102,102)" frame="true" keypad-type="None" font-sizepx="29" wrapping="true" width="210" cx="107.56"/> <dataLinks> <dataLink tag="THISISATAG" tagType="boolean" widgetType="Project" attribute="frameFill" sourceType="Tag" tagIndex="-1" dataSource="_TagMgr" class="TagMgrWgt" readWrite="R"> <xForms> <xForm name="ColorPaletteCustom" ColorPaletteCustom="#707070;#009942" class="ColorPaletteCustomXForm"> <value i="0">0</value> <value i="1">1</value> </xForm> </xForms> </dataLink> </dataLinks> <links> <lang textid="37" class="MLTextLink"/> </links> </object> <object id="MAINOBJ@$GroupSubscrWgt@$0" class="GroupSubscribeWgt"> <wgtStyle width="0" height="0" x="0" y="0"/> </object> </wgtPage>
我尝试的XSLT模板
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <xsl:output method="xml" indent="yes" omit-xml-declaration="no"/> <xsl:strip-space elements="*"/> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"> <xsl:sort select="@id" data-type="text"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
修正后的XSLT实现
要同时实现属性按字母排序和同级元素按字母排序,需要分开处理属性和元素:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> <!-- 输出格式化的XML,保留声明 --> <xsl:output method="xml" indent="yes" omit-xml-declaration="no" encoding="UTF-8"/> <!-- 去除多余空白 --> <xsl:strip-space elements="*"/> <!-- 匹配所有节点和属性的基础模板 --> <xsl:template match="@*|node()"> <xsl:copy> <!-- 先处理属性:按属性名称字母排序 --> <xsl:apply-templates select="@*"> <xsl:sort select="name()" data-type="text" order="ascending"/> </xsl:apply-templates> <!-- 再处理子元素:按元素名称字母排序;同类型元素按id属性排序 --> <xsl:apply-templates select="node()"> <xsl:sort select="name()" data-type="text" order="ascending"/> <xsl:sort select="@id" data-type="text" order="ascending"/> </xsl:apply-templates> </xsl:copy> </xsl:template> </xsl:stylesheet>
关键说明
- 属性排序:对所有属性应用模板时,通过
<xsl:sort select="name()"/>按属性名称的字母顺序排列。 - 元素排序:对子元素先按元素名称排序;如果是同类型元素(比如多个
<MLText>),再按id属性排序,确保同类型元素内部也有序。 - 原模板问题:仅按
@id排序,未处理属性排序逻辑,且对无id属性的元素排序规则不完整,导致部分内容未按预期排序。
内容的提问来源于stack exchange,提问作者user2239318
相关产品推荐
相关产品推荐

