Chắc chắn, không có vấn đề:
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output indent="yes" />
<xsl:template match="/data">
<!-- copy the document element -->
<xsl:copy>
<!-- That's where we start: all "record" nodes that have no "\". -->
<xsl:apply-templates mode="recurse" select="/data/record[
not(contains(@Name, '\'))
]" />
</xsl:copy>
</xsl:template>
<xsl:template match="record" mode="recurse">
<xsl:param name="starting-path" select="''" />
<!-- The record node and its ID attribute can be copied. -->
<xsl:copy>
<xsl:copy-of select="@ID" />
<!-- Create the new "name" attribute. -->
<xsl:attribute name="Name">
<xsl:value-of select="substring-after(@Name, $starting-path)" />
</xsl:attribute>
<!-- Append a backslash to the current path. -->
<xsl:variable name="current-path" select="concat(@Name, '\')" />
<!-- Select all "record" nodes that are one level deeper... -->
<xsl:variable name="children" select="/data/record[
starts-with(@Name, $current-path)
and
not(contains(substring-after(@Name, $current-path), '\'))
]" />
<!-- ...and apply this template to them. -->
<xsl:apply-templates mode="recurse" select="$children">
<xsl:with-param name="starting-path" select="$current-path" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output trên hệ thống của tôi:
<data>
<record ID="26" Name="category 1">
<record ID="24" Name="sub category 1">
<record ID="25" Name="sub category 2"></record>
<record ID="27" Name="sub category 3"></record>
</record>
</record>
</data>
Lưu ý rằng toàn bộ giải pháp dựa trên giả định rằng tất cả các con đường là kinh điển và không chứa dấu xồ nguợc trailing .
Cũng lưu ý rằng mọi phần tử "bản ghi" chưa từng có/mồ côi sẽ không ở đầu ra (trừ khi chúng ở cấp cơ sở, dĩ nhiên).
Một điều nữa: Chế độ mẫu ("recurse") là không cần thiết. Tôi đã bao gồm nó vì mẫu đang làm điều gì đó khá đặc biệt và có thể có một mẫu khác trong giải pháp của bạn khớp với các nút "ghi". Trong trường hợp này, giải pháp này có thể được giảm xuống mà không vi phạm bất cứ điều gì khác. Đối với giải pháp độc lập, các chế độ mẫu có thể bị xóa bất cứ lúc nào.
Oh, và điều cuối cùng: Nếu bạn muốn tài liệu kết quả để được sắp xếp theo tên, bao gồm <xsl:sort>
element với <xsl:apply-templates>
(cả hai lần xuất hiện), như vậy:
<xsl:apply-templates select="...">
<xsl:sort select="@Name" data-type="text" order="ascending" />
</xsl:apply-templates>
@myso: "tiểu mục 3 "có cùng cấp với" danh mục phụ 2 "trong XML đầu vào của bạn. Nó không thể lồng nhau theo cách bạn hiển thị trong XML đầu ra của bạn. – Tomalak
Vâng, sai lầm của tôi. Đã chỉnh sửa nó. – mysomic