如何复制XML文档中引用的元素?附示例XML文档
Got it, let's figure out how to copy those referenced user elements into your posts. The core task here is replacing the user ID tags in each post with the full corresponding user element from the <users> section (or adding it alongside—we'll focus on replacement since it's the most common use case). Here are two straightforward methods to get this done:
Method 1: Using XSLT (Recommended for XML Transformations)
XSLT is designed specifically for XML manipulation, so it's the cleanest approach here. Here's a stylesheet that will handle the transformation:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Identity template: copies all elements/attributes as-is by default --> <xsl:template match="@*|node()"> <xsl:copy> <xsl:apply-templates select="@*|node()"/> </xsl:copy> </xsl:template> <!-- Targets <user> tags inside posts, replaces them with full user elements --> <xsl:template match="posts/post/user"> <!-- Look up the matching user by ID and copy it --> <xsl:copy-of select="/root/users/user[@id = current()]"/> </xsl:template> </xsl:stylesheet>
How it works:
- The identity template ensures every part of your original XML is preserved unless we override it with a specific rule.
- The second template zeroes in on
<user>tags inside posts. It uses an XPath query to find the user element in the<users>section where theidattribute matches the text of the current post's user tag, then copies that full element into the post.
Applying the stylesheet:
Use a command-line tool like xsltproc to run the transformation:
xsltproc transform.xsl source.xml > output.xml
Your resulting XML will look like this (with full user elements in each post):
<root> <users> <user id="1" name="user 1" /> <user id="2" name="user 2" /> <user id="3" name="user 3" /> </users> <posts> <post> <user id="1" name="user 1" /> <text>First sample post!</text> <status>DELETED</status> </post> <post> <user id="2" name="user 2" /> <text>Second sample post!</text> <status>ACTIVE</status> </post> </posts> </root>
Method 2: Using Python (Programmatic Approach)
If you prefer coding over XSLT, Python's built-in xml.etree.ElementTree module can handle this easily. Here's a script:
import xml.etree.ElementTree as ET # Parse the source XML tree = ET.parse('source.xml') root = tree.getroot() # Create a map of user IDs to their elements for quick lookup user_lookup = {user.get('id'): user for user in root.findall('users/user')} # Update each post's user tag for post in root.findall('posts/post'): user_id_tag = post.find('user') if user_id_tag is not None: user_id = user_id_tag.text if user_id in user_lookup: # Replace the ID tag with the full user element post.remove(user_id_tag) post.insert(0, ET.copy(user_lookup[user_id])) # Save the modified XML tree.write('output.xml', encoding='utf-8', xml_declaration=True)
How it works:
- First, we build a dictionary that maps each user ID to its corresponding element—this makes lookups fast.
- We loop through each post, find the user ID tag, remove it, and insert a copy of the full user element in its place.
- Finally, we save the updated XML to a new file.
Quick Notes:
- If you want to keep the original user ID tag and add the full user element next to it, just skip the
post.remove(user_id_tag)line in the Python script, or adjust the XSLT template to copy both elements. - Make sure your source XML is well-formed (your original snippet was cut off, but assuming the full document is valid).
内容的提问来源于stack exchange,提问作者raven-king

