You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用XSL结合Java DOM对XML按属性排序并保存?

问题

使用Java DOM读取XML并插入新元素后,希望保存时通过XSL按title属性对XML的<movie>元素排序。

现有XML:

<movie-theater>
    <catalog>
      <movie title="StarWars" director="George Lucas" madeIn="Holliwood"/>
      <movie title="LordOfTheRings" director="Peter Jackson" madeIn="New Zeland"/>
      <movie title="Batman" director="Tim Burton" madeIn="Holliwood"/>
    </catalog>
</movie-theater>

期望排序后的XML:

<movie-theater>
    <catalog>
      <movie title="Batman" director="Tim Burton" madeIn="Holliwood"/>
      <movie title="LordOfTheRings" director="Peter Jackson" madeIn="New Zeland"/>
      <movie title="StarWars" director="George Lucas" madeIn="Holliwood"/>
    </catalog>
</movie-theater>

你尝试的XSL模板:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/movie-theater/catalog">
        <xsl:for-each select="movie">
            <xsl:sort select="@title"/>
            <xsl:value-of select="."/>              
        </xsl:for-each>
    </xsl:template>
</xsl:stylesheet>
修正方案

你的XSL模板存在两个关键问题:

  1. <xsl:value-of select="."/>仅输出元素的文本内容,但<movie>是自闭合元素,无文本内容,因此不会生成任何节点代码;需用<xsl:copy-of select="."/>复制整个<movie>节点。
  2. 模板仅匹配了<catalog>节点,未处理外层<movie-theater>根节点,最终输出会丢失XML的整体结构。

正确的XSL模板如下:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <!-- 身份模板:原样复制所有未被特定模板匹配的节点和属性,保留XML整体结构 -->
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>

    <!-- 针对catalog节点,对内部movie元素按title属性升序排序 -->
    <xsl:template match="catalog">
        <xsl:copy>
            <xsl:apply-templates select="movie">
                <xsl:sort select="@title" order="ascending" case-order="upper-first"/>
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

模板说明

  • 第一个模板是身份模板,保证XML中未被特殊处理的节点(比如<movie-theater>根节点)和属性都能原样保留。
  • 第二个模板专门处理<catalog>节点,对其下的<movie>元素按title属性升序排序,再复制每个排序后的节点,实现需求效果。
Java 代码示例

以下是结合DOM修改XML后,使用XSLT转换并保存的完整代码:

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class XmlSortExample {
    public static void main(String[] args) {
        try {
            // 1. 读取XML文件到DOM对象
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            Document doc = dbf.newDocumentBuilder().parse("input.xml");

            // 2. 插入新的movie元素(示例操作,可替换为你的业务逻辑)
            Element newMovie = doc.createElement("movie");
            newMovie.setAttribute("title", "Inception");
            newMovie.setAttribute("director", "Christopher Nolan");
            newMovie.setAttribute("madeIn", "Holliwood");
            doc.getElementsByTagName("catalog").item(0).appendChild(newMovie);

            // 3. 加载XSLT排序模板
            TransformerFactory tf = TransformerFactory.newInstance();
            StreamSource xsltSource = new StreamSource("sort.xsl");
            Transformer transformer = tf.newTransformer(xsltSource);

            // 4. 执行转换并保存到输出文件
            DOMSource source = new DOMSource(doc);
            StreamResult result = new StreamResult("output.xml");
            transformer.transform(source, result);

            System.out.println("XML已排序并保存成功");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

内容的提问来源于stack exchange,提问作者Lazaruss

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 14:10:04