排序使用XSLT
问题描述:
输入XML的XML:排序使用XSLT
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:Username>User</wsse:Username>
<wsse:Password>Password</wsse:Password>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<soap-env:CustomerRs>
<Information>
<Identity Code="DFW">
<User LoginID="123456" />
</Identity>
<User>
<Customer Gender="Male">
<Person>
<GivenName>Tester2</GivenName>
<LastName>Tester</LastName>
</Person>
<Telephone Type="Business" InfoNo="1" SeqNo="1">
<Number Area="456" Phone="7878787" />
</Telephone>
<Info InfoNo="2" SeqNo="1">
<LastName>Wilson</LastName>
<GivenName>Kelley</GivenName>
</Info>
<Info InfoNo="4" SeqNo="1">
<LastName>Graham</LastName>
<GivenName>Tom</GivenName>
</Info>
<Info InfoNo="1" SeqNo="3">
<LastName>Fisher</LastName>
<GivenName>Elaine</GivenName>
</Info>
<Info InfoNo="1" SeqNo="2">
<LastName>Gary</LastName>
<GivenName>Jerry</GivenName>
</Info>
<Info InfoNo="1" SeqNo="1">
<LastName>Timothy</LastName>
<GivenName>Kathy</GivenName>
</Info>
<Info InfoNo="3" SeqNo="1">
<LastName>Tim</LastName>
<GivenName>Kerry</GivenName>
</Info>
<Info InfoNo="1" SeqNo="4">
<LastName>Rob</LastName>
<GivenName>Tony</GivenName>
</Info>
<Address Type="Business" InfoNo="1" SeqNo="1">
<Line1>Menands Ln</Line1>
<City>Albany</City>
</Address>
</Customer>
<Order type="S">
<Ref>ABC123</Ref>
<OrderedBy>
<Debtor code="BLABLA"></Debtor>
</OrderedBy>
<DeliveryMethod code="Barefoot"></DeliveryMethod>
<OrderLine line="1">
<Item code="QQQ123456"></Item>
<Quantity>1</Quantity>
</OrderLine>
</Order>
</User>
</Information>
</soap-env:CustomerRs>
</soap-env:Body>
</soap-env:Envelope>
期望输出XML响应:
<soap-env:Envelope xmlns:soap-env="http://schemas.xmlsoap.org/soap/envelope/">
<soap-env:Header>
<wsse:Security xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:Username>User</wsse:Username>
<wsse:Password>Password</wsse:Password>
</wsse:Security>
</soap-env:Header>
<soap-env:Body>
<soap-env:CustomerRs>
<Information>
<Identity Code="DFW">
<User LoginID="123456" />
</Identity>
<User>
<Customer Gender="Male">
<Person>
<GivenName>Tester2</GivenName>
<LastName>Tester</LastName>
</Person>
<Telephone Type="Business" InfoNo="1" SeqNo="1">
<Number Area="456" Phone="7878787" />
</Telephone>
<Info InfoNo="1" SeqNo="1">
<LastName>Timothy</LastName>
<GivenName>Kathy</GivenName>
</Info>
<Info InfoNo="1" SeqNo="2">
<LastName>Gary</LastName>
<GivenName>Jerry</GivenName>
</Info>
<Info InfoNo="1" SeqNo="3">
<LastName>Fisher</LastName>
<GivenName>Elaine</GivenName>
</Info>
<Info InfoNo="1" SeqNo="4">
<LastName>Rob</LastName>
<GivenName>Tony</GivenName>
</Info>
<Info InfoNo="2" SeqNo="1">
<LastName>Wilson</LastName>
<GivenName>Kelley</GivenName>
</Info>
<Info InfoNo="3" SeqNo="1">
<LastName>Tim</LastName>
<GivenName>Kerry</GivenName>
</Info>
<Info InfoNo="4" SeqNo="1">
<LastName>Graham</LastName>
<GivenName>Tom</GivenName>
</Info>
<Address Type="Business" InfoNo="1" SeqNo="1">
<Line1>Menands Ln</Line1>
<City>Albany</City>
</Address>
</Customer>
<Order type="S">
<Ref>ABC123</Ref>
<OrderedBy>
<Debtor code="BLABLA"></Debtor>
</OrderedBy>
<DeliveryMethod code="Barefoot"></DeliveryMethod>
<OrderLine line="1">
<Item code="QQQ123456"></Item>
<Quantity>1</Quantity>
</OrderLine>
</Order>
</User>
</Information>
</soap-env:CustomerRs>
</soap-env:Body>
</soap-env:Envelope>
我的XSLT是做转型:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="/*[local-name()='Envelope']">
<xsl:copy>
<xsl:apply-templates select="@*|node()">
<xsl:sort select="/*[local-name()='Info']/@*[local-name()='InfoNo']" data-type="number" order="ascending" />
<xsl:sort select="/*[local-name()='Info']/@*[local-name()='SeqNo']" data-type="number" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我用这个样式表进行排序并安排,但仍然生产相同的输入。我做错了什么,我无法得到答复。
答
请考虑以下调整。对于排序,由于您使用标识模板按原样复制文档,因此无需遍历整个树。只需添加一个排序部分的模板,即父标签,这里是<Customer>
,然后只排序其<Info>
子女。
此外,InfoNo和的SeqNo的属性,所以必须用@
引用。最后,最佳做法是尝试在XSLT顶部添加<xsl:strip-space elements="*"/>
以删除空白文本节点,这样可以增加一点效率,因为这些节点会从内存中分离出来。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Customer">
<xsl:copy>
<xsl:copy-of select="Person|Telephone"/>
<xsl:apply-templates select="Info">
<xsl:sort select="@InfoNo" data-type="number" order="ascending" />
<xsl:sort select="@SeqNo" data-type="number" order="ascending" />
</xsl:apply-templates>
<xsl:copy-of select="Address"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
答
您需要了解相对路径和绝对路径之间的区别。要计算元素E的排序关键字,您将(几乎)总是要使用从E开始的路径(即相对路径)选择某个值。以“/”开头的路径是绝对路径,它始于文档的顶部,因此计算相同的值,而不管E在哪里。因此,使用绝对路径计算的排序关键字(如<xsl:sort select="/*[.....]"/>
)必须是错误的。