大家好,感谢您的帮助。 我必须转换父节点及其所有子节点,但我不太了解XSLT的功能。
一旦选择
我有以下XML代码:
<NetworkAliases>
<NetAlias UID="{02A4738B-605C-4641-9705-E83ADFDAB221}" ZoneType="1" Name="comodo">
<AddressItems>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="114.255.52.160" AddrEnd="114.255.52.175"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="123.124.255.96" AddrEnd="123.124.255.111"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="69.195.46.36" AddrEnd="255.255.6.39"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="97.107.169.84" AddrEnd="97.107.169.87"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="97.107.175.140" AddrEnd="97.107.175.143"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="199.66.200.0" AddrEnd="199.66.207.255"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="208.49.40.28" AddrEnd="208.49.40.31"/>
</Address>
<Address Source="2" Type="2">
<IPV6 AddrType="4" AddrMask="48" AddrBase="2607F7A80E0A00000000000000000000"/>
</Address>
<Address Source="2" Type="2">
<IPV6 AddrType="4" AddrMask="48" AddrBase="2607F7A8100900000000000000000000"/>
</Address>
</AddressItems>
</NetAlias>
<NetAlias UID="{0B9F7F4D-E23B-4D09-88F8-0CA378319316}" ZoneType="1" Name="akamai">
<AddressItems>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="2.22.80.0" AddrEnd="2.22.95.255"/>
</Address>
<Address Source="2" Type="2">
<IPV6 AddrType="4" AddrMask="48" AddrBase="2A0226F000DF00000000000000000000"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="95.100.224.0" AddrEnd="95.100.239.255"/>
</Address>
</AddressItems>
</NetAlias>
</NetworkAliases>
和此xsl(适用于其他节点,但不适用于此节点):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="no" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:template match="PolicyItems">
<xsl:copy>
<xsl:apply-templates select="PolicyItem">
<xsl:sort select="@Filename" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="Predefined">
<xsl:copy>
<xsl:apply-templates select="PredefinedItem">
<xsl:sort select="@Name" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="NetworkAliases">
<xsl:copy>
<xsl:apply-templates select="NetAlias">
<xsl:sort select="@Name" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="AddressItems">
<xsl:copy>
<xsl:apply-templates select="Address">
<xsl:sort select="@Type" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="PortAliases">
<xsl:copy>
<xsl:apply-templates select="PortAlias">
<xsl:sort select="@Name" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<!-- To Sort also the ports -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
结果应为:
<NetworkAliases>
<NetAlias UID="{0B9F7F4D-E23B-4D09-88F8-0CA378319316}" ZoneType="1" Name="akamai">
<AddressItems>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="2.22.80.0" AddrEnd="2.22.95.255"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="95.100.224.0" AddrEnd="95.100.239.255"/>
</Address>
<Address Source="2" Type="2">
<IPV6 AddrType="4" AddrMask="48" AddrBase="2A0226F000DF00000000000000000000"/>
</Address>
</AddressItems>
</NetAlias>
<NetAlias UID="{02A4738B-605C-4641-9705-E83ADFDAB221}" ZoneType="1" Name="comodo">
<AddressItems>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="69.195.46.36" AddrEnd="255.255.6.39"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="97.107.169.84" AddrEnd="97.107.169.87"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="97.107.175.140" AddrEnd="97.107.175.143"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="114.255.52.160" AddrEnd="114.255.52.175"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="123.124.255.96" AddrEnd="123.124.255.111"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="199.66.200.0" AddrEnd="199.66.207.255"/>
</Address>
<Address Source="2" Type="1">
<IPV4 AddrType="2" AddrStart="208.49.40.28" AddrEnd="208.49.40.31"/>
</Address>
<Address Source="2" Type="2">
<IPV6 AddrType="4" AddrMask="48" AddrBase="2607F7A80E0A00000000000000000000"/>
</Address>
<Address Source="2" Type="2">
<IPV6 AddrType="4" AddrMask="48" AddrBase="2607F7A8100900000000000000000000"/>
</Address>
</AddressItems>
</NetAlias>
</NetworkAliases>
我尝试了很多次都没有结果,最后我不得不问你。谢谢
答案 0 :(得分:0)
我假设您可以使用XSLT-2.0,因为您的xsl:stylesheet
的版本标记表明是这样。
您可以通过使用XSLT-2.0排序函数(此处为sort:IPV4sorting
)来实现自己的目标,该函数具有自己的命名空间(此处为xmlns:sort="http://www.sort.ns"
)。
将其放在一起,您将获得以下(部分)样式表。您只需要替换AddressItems
模板并添加xsl:function
。您的其余代码可以保持不变。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:sort="http://www.sort.ns">
...
<xsl:function name="sort:IPV4sorting" as="xs:string">
<xsl:param name="ipv4" as="xs:string"/>
<xsl:variable name="numKey">
<xsl:analyze-string select="$ipv4" regex="(\d+)\.(\d+)\.(\d+)\.(\d+)">
<xsl:matching-substring>
<xsl:value-of select="concat(format-number(xs:integer(regex-group(1)),'000'),format-number(xs:integer(regex-group(2)),'000'),format-number(xs:integer(regex-group(3)),'000'),format-number(xs:integer(regex-group(4)),'000'))" />
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:variable>
<xsl:value-of select="$numKey" />
</xsl:function>
<xsl:template match="AddressItems">
<xsl:copy>
<xsl:apply-templates select="Address[IPV4]">
<xsl:sort select="sort:IPV4sorting(IPV4/@AddrStart)" order="ascending" />
</xsl:apply-templates>
<xsl:apply-templates select="Address[IPV6]">
<xsl:sort select="@AddrBase" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
...
此代码使用IPv4地址中的xsl:analyze-string
创建一个12位的键值(4 * 3 = 12),该地址用作排序功能中的排序键。它确实调用xsl:apply-templates
两次以处理与IPv4地址不同的IPv6地址。
答案 1 :(得分:0)
在<xsl:sort>
内考虑多个<xsl:for-each>
,然后迁移父 Address 节点的属性。另外,使用substring-before
检索IP地址中第一个句点之前的数字,这似乎是您的排序标准(而不是数字的全长)。
请注意:下面省略了当前XML中没有的模板: PolicyItems , Predefined , PortAliases 。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" standalone="no" indent="yes" />
<xsl:strip-space elements="*" />
<!-- IDENTITY TRANSFORM -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="NetworkAliases">
<xsl:copy>
<xsl:apply-templates select="NetAlias">
<xsl:sort select="@Name" order="ascending" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
<xsl:template match="AddressItems">
<xsl:copy>
<xsl:for-each select="Address/*">
<xsl:sort select="@AddrType" order="ascending" data-type="number"/>
<xsl:sort select="format-number(substring-before(@AddrStart, '.'), '#')"
order="ascending" data-type="number"/>
<xsl:sort select="AddrBase" order="ascending" data-type="text"/>
<Address>
<xsl:copy-of select="ancestor::Address/@*"/>
<xsl:copy-of select="."/>
</Address>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>