如何用XQuery编写函数校验文件系统资源路径名是否唯一
Hey there! Let's work through this XQuery problem together. Since you didn't share the exact DTD structure, I'll go with standard assumptions for a filesystem XML setup that aligns with your note about unspecified elements containing PCData:
- Root element is
<filesystem> - Folders are
<folder>elements with anameattribute, and can contain nested<folder>or<file>elements - Files are
<file>elements with anameattribute - Any other elements just hold plain text, so we can ignore them for resource path checks
Here's a solution that creates a boolean-returning function to verify all resource paths are unique:
declare function local:all-paths-unique($fs as element(filesystem)) as xs:boolean { (: Collect every full path for files and folders :) let $all-resource-paths := local:get-full-resource-paths($fs, "") :(: If distinct paths count matches total count, all are unique :) return count(distinct-values($all-resource-paths)) eq count($all-resource-paths) }; (: Helper function to recursively build full paths for all resources :) declare function local:get-full-resource-paths($node as element(), $current-path as xs:string) as xs:string* { (: Process folders: add their path, then recurse into children :) if ($node instance of element(folder)) then let $folder-full-path := if ($current-path eq "") then $node/@name else concat($current-path, "/", $node/@name) return ($folder-full-path, local:get-full-resource-paths($node/*, $folder-full-path)) (: Process files: return their full path :) else if ($node instance of element(file)) then concat($current-path, "/", $node/@name) (: Skip non-resource elements but recurse into their children just in case :) else local:get-full-resource-paths($node/*, $current-path) };
How this works:
Main function (
local:all-paths-unique):- Calls the helper function to gather every full path from the filesystem.
- Compares the number of distinct paths to the total number of paths. If they're equal, all paths are unique (returns
true()); if not, there's a duplicate (returnsfalse()).
Helper function (
local:get-full-resource-paths):- Recursively traverses the XML structure:
- For folders, it builds the full path by appending the folder's name to the current parent path, then returns that path plus all paths from the folder's children.
- For files, it appends the file's name to the current path and returns that full path.
- For any other elements (which hold PCData per your DTD), it skips the element itself but still checks its children (a safe fallback in case resources are nested unexpectedly).
- Recursively traverses the XML structure:
Example usage:
If your filesystem XML looks like this:
<filesystem> <folder name="projects"> <file name="todo.md"/> <folder name="xquery-practice"> <file name="path-check.xq"/> </folder> </folder> <folder name="downloads"> <file name="archive.zip"/> </folder> </filesystem>
Calling local:all-paths-unique(/filesystem) will return true(). But if you add a duplicate path (like another <file name="todo.md"/> directly under <filesystem>), the function will return false().
内容的提问来源于stack exchange,提问作者Hichame Yessou

