我正在使用xslt对xml文件进行排序,我在这里遇到小问题..
我的XML文件如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<bulkCmConfigDataFile xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="a.xsd a.xsd">
<fileHeader fileFormatVersion="32.615 V5.0"/>
<configData dnPrefix="" log="0" mediation="false">
<subs:SuMSubscriberProfile id="378466">
<subs:SuMSubscriptionProfile id="1">
<subs:ImsServiceProfile id="1" modifier="create">
<subs:attributes>
<subs:chargingIdx>1</subs:chargingIdx>
</subs:attributes>
</subs:ImsServiceProfile>
</subs:SuMSubscriptionProfile>
</subs:SuMSubscriberProfile>
<subs:SuMSubscriberProfile id="378460">
<subs:SuMSubscriptionProfile id="1">
<subs:ImsServiceProfile id="1" modifier="create">
<subs:attributes>
<subs:chargingIdx>2</subs:chargingIdx>
</subs:attributes>
</subs:ImsServiceProfile>
</subs:SuMSubscriptionProfile>
</subs:SuMSubscriberProfile>
</configData>
<fileFooter dateTime="2015-03-14T10:10:10"/>
</bulkCmConfigDataFile>
我正在使用以下样式表:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="a.xsd"
xmlns:xn="b.xsd" xmlns:subs="c.xsd">
<xsl:output method="xml" indent="yes" version="1.0"
encoding="ISO-8859-1" />
<xsl:strip-space elements="*" />
<xsl:param name="outerMatchElement" />
<xsl:param name="innerMatchElement" />
<xsl:param name="sortBy" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()=$outerMatchElement]">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:choose>
<xsl:when test="count(*[name()=$innerMatchElement]) = 0">
<xsl:apply-templates select="*[name()=$sortBy]">
<xsl:sort select="@id" data-type="number" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="count(*[name()=$innerMatchElement]) = 1">
<xsl:apply-templates select="*[name()=$innerMatchElement]/*[name()=$sortBy]">
<xsl:sort select="@id" data-type="number" />
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="*[name()=$innerMatchElement]">
<xsl:sort select="*[name()=$sortBy]/@id" data-type="number" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
其中outerMatchElement = bulkCmConfigDataFile,innerMatchElement = configData ,sortBy = subs:SuMSubscriberProfile
我使用此样式表获得以下结果:
<?xml version="1.0" encoding="ISO-8859-1"?><bulkCmConfigDataFile xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="configData.xsd configData.xsd">
<subs:SuMSubscriberProfile id="378460">
<subs:SuMSubscriptionProfile id="1">
<subs:ImsServiceProfile id="1" modifier="create">
<subs:attributes>
<subs:chargingIdx>2</subs:chargingIdx>
</subs:attributes>
</subs:ImsServiceProfile>
</subs:SuMSubscriptionProfile>
</subs:SuMSubscriberProfile>
<subs:SuMSubscriberProfile id="378466">
<subs:SuMSubscriptionProfile id="1">
<subs:ImsServiceProfile id="1" modifier="create">
<subs:attributes>
<subs:chargingIdx>1</subs:chargingIdx>
</subs:attributes>
</subs:ImsServiceProfile>
</subs:SuMSubscriptionProfile>
</subs:SuMSubscriberProfile>
</bulkCmConfigDataFile>
预期输出如下:
<?xml version="1.0" encoding="ISO-8859-1"?>
<bulkCmConfigDataFile xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="configData.xsd configData.xsd">
<fileHeader fileFormatVersion="32.615 V5.0"/>
<configData dnPrefix="" log="0" mediation="false">
<subs:SuMSubscriberProfile id="378460">
<subs:SuMSubscriptionProfile id="1">
<subs:ImsServiceProfile id="1" modifier="create">
<subs:attributes>
<subs:chargingIdx>2</subs:chargingIdx>
</subs:attributes>
</subs:ImsServiceProfile>
</subs:SuMSubscriptionProfile>
</subs:SuMSubscriberProfile>
<subs:SuMSubscriberProfile id="378466">
<subs:SuMSubscriptionProfile id="1">
<subs:ImsServiceProfile id="1" modifier="create">
<subs:attributes>
<subs:chargingIdx>1</subs:chargingIdx>
</subs:attributes>
</subs:ImsServiceProfile>
</subs:SuMSubscriptionProfile>
</subs:SuMSubscriberProfile>
</configData>
<fileFooter dateTime="2015-03-14T10:10:10"/>
</bulkCmConfigDataFile>
您会注意到文件标题和文件页脚标签在我输出的输出中缺失,请指导我如何解决此问题?我正在尝试为我的xml文件制作通用的排序过程。
答案 0 :(得分:1)
在给定的输入样本中,只有1个元素与$innerMatchElement
变量匹配,因此第二个xsl:when
适用。但是,在这种情况下执行的相关代码块中,您只选择“innerMatchElement”元素的子元素,因此忽略任何其他子元素。
请尝试将第二个xsl:when
更改为此。
<xsl:when test="count(*[name()=$innerMatchElement]) = 1">
<xsl:apply-templates select="*[following-sibling::*[name()=$innerMatchElement]]" />
<xsl:apply-templates select="*[name()=$innerMatchElement]/*[name()=$sortBy]">
<xsl:sort select="@id" data-type="number" />
</xsl:apply-templates>
<xsl:apply-templates select="*[preceding-sibling::*[name()=$innerMatchElement]]" />
</xsl:when>
因此,您最初选择在“innermatchElement”元素之前出现的元素,然后选择内部匹配元素,最后选择之后出现的元素。
您可能需要在其他两个条件中添加类似的行。
注意,如果你也想要“innerMatchElement”标签,你可以通过创建一个xsl:element
<xsl:when test="count(*[name()=$innerMatchElement]) = 1">
<xsl:apply-templates select="*[following-sibling::*[name()=$innerMatchElement]]" />
<xsl:element name="{$innerMatchElement}">
<xsl:apply-templates select="*[name()=$innerMatchElement]/@*" />
<xsl:apply-templates select="*[name()=$innerMatchElement]/*[name()=$sortBy]">
<xsl:sort select="@id" data-type="number" />
</xsl:apply-templates>
</xsl:element>
<xsl:apply-templates select="*[preceding-sibling::*[name()=$innerMatchElement]]" />
</xsl:when>
或者,您可以更好地使用模板匹配。试试这个XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="a.xsd" xmlns:xn="b.xsd" xmlns:subs="c.xsd">
<xsl:output method="xml" indent="yes" version="1.0" encoding="ISO-8859-1" />
<xsl:strip-space elements="*" />
<xsl:param name="outerMatchElement" select="'bulkCmConfigDataFile'" />
<xsl:param name="innerMatchElement" select="'configData'" />
<xsl:param name="sortBy" select="'subs:SuMSubscriberProfile'" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()=$outerMatchElement]">
<xsl:copy>
<xsl:copy-of select="@*" />
<xsl:choose>
<xsl:when test="count(*[name()=$innerMatchElement]) = 0">
<xsl:apply-templates select="*[name()=$sortBy]">
<xsl:sort select="@id" data-type="number" />
</xsl:apply-templates>
</xsl:when>
<xsl:when test="count(*[name()=$innerMatchElement]) = 1">
<xsl:apply-templates select="*[name()=$innerMatchElement]" mode="single" />
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="*[name()=$innerMatchElement]">
<xsl:sort select="*[name()=$sortBy]/@id" data-type="number" />
</xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:copy>
</xsl:template>
<xsl:template match="*[name()=$innerMatchElement]" mode="single">
<xsl:apply-templates select="preceding-sibling::*" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates select="*[name()=$sortBy]">
<xsl:sort select="@id" data-type="number" />
</xsl:apply-templates>
</xsl:copy>
<xsl:apply-templates select="following-sibling::*" />
</xsl:template>
</xsl:stylesheet>
顺便说一句,在XSLT 1.0中,模板匹配中的变量实际上是一个错误(参见http://www.w3.org/TR/xslt#section-Defining-Template-Rules),所以这实际上应该失败
<xsl:template match="*[name()=$outerMatchElement]">
但是,某些XSLT 1.0允许它,就像你的情况一样。如果你切换到一个出错的处理器,解决方案就是做这样的事情......
<xsl:template match="*">
<xsl:choose>
<xsl:when test="name()=$outerMatchElement">
<!-- Existing code -->
</xsl:when>
<xsl:otherwise>
<!-- Identity Template -->
</xsl:otherwise>
</xsl:choose>
</xsl:template>