与使用DOM解析器手动解析XML文件相比,使用XSLT样式表是否有任何优势

对于我们的一个应用程序,我编写了一个使用java的DOM解析器的实用程序。 它基本上采用XML文件,解析它,然后使用以下方法之一处理数据以实际检索数据。

getElementByTagName() getElementAtIndex() getFirstChild() getNextSibling() getTextContent() 

现在我必须做同样的事情,但我想知道使用XSLT样式表是否会更好。 向我们发送XML文件的组织不断更改其架构意味着我们必须更改我们的代码以满足这些shema更改。 我不太熟悉XSLT进程,所以我试图找出是否更好地使用XSLT样式表而不是“手动解析”。

XSLT样式表看起来很有吸引力的原因是我认为如果XML文件的架构发生变化,我只需要更改样式表吗? 它是否正确?

另一件我想知道的是两者中的哪一个(XSLT转换器或DOM解析器)性能更好。 对于手动选项,我只使用DOM解析器来解析xml文件。 XSLT转换器如何实际解析文件? 与手动解析xml文件相比,它是否包含额外的开销? 我问的原因是性能很重要,因为我将处理的数据的性质。

任何建议?

谢谢

编辑

基本上我目前正在做的是解析一个xml文件并处理一些xml元素中的值。 我不会将xml文件转换为任何其他格式。 我只是提取一些值,从Oracle数据库中提取一行并将一个新行保存到另一个表中。 我解析的xml文件只包含用于从数据库中检索某些数据的引用值。

xslt不适合这种情况吗? 如果架构发生变化,是否有更好的方法可以避免代码更改?

编辑2

对于我对XML数据所做的事情不够清楚而道歉。 基本上有一个包含一些信息的XML文件。 我从XML文件中提取此信息,并使用它从本地数据库中检索更多信息。 xml文件中的数据更像是数据库中所需数据的引用键。 然后,我使用XML文件中的特定密钥获取从XML文件中提取的内容以及从数据库中检索的内容,并将该数据保存到另一个数据库表中。

我遇到的问题是我知道如何编写一个DOM解析器来从XML文件中提取我需要的信息,但我想知道是否使用XSLT样式表是一个更好的选择,因为如果架构更改我不会更改代码。

阅读下面的回复听起来像XSLT仅用于转换和XML文件到另一个XML文件或其他格式。 鉴于我不打算转换XML文件,可能不需要添加解析XSLT样式表以及XML文件的额外开销。

我认为你需要的实际上是一个XPath表达式。 您可以在某些属性文件中配置该表达式,也可以使用任何用于检索设置参数的表达式。

这样,只要您的客户隐藏您在其他地方使用的信息,就可以更改XPath表达式。

基本上,XSLT是一种矫枉过正,你只需要一个XPath表达式。 单个XPath表达式将允许归入您所追求的每个值。

更新

由于我们现在谈论的是JDK 1.4,我在下面列出了使用XPath在XML文件中获取文本的3种不同方法。 (尽可能简单,我害怕没有NPE警卫绒毛;-)

从最新的开始。

0.首先是示例XML配置文件

   250 5000  

1.使用Java SE 5.0的JAXP 1.3标准部分

 import javax.xml.parsers.*; import javax.xml.xpath.*; import org.w3c.dom.Document; public class TestXPath { private static final String CFG_FILE = "test.xml" ; private static final String XPATH_FOR_PRM_MaxThread = "/config/param[@id='MaxThread']/text()"; public static void main(String[] args) { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); DocumentBuilder builder; try { builder = docFactory.newDocumentBuilder(); Document doc = builder.parse(CFG_FILE); XPathExpression expr = XPathFactory.newInstance().newXPath().compile(XPATH_FOR_PRM_MaxThread); Object result = expr.evaluate(doc, XPathConstants.NUMBER); if ( result instanceof Double ) { System.out.println( ((Double)result).intValue() ); } } catch (Exception e) { e.printStackTrace(); } } } 

2.使用Java SE 1.4-2的JAXP 1.2标准部分

 import javax.xml.parsers.*; import org.apache.xpath.XPathAPI; import org.w3c.dom.*; public class TestXPath { private static final String CFG_FILE = "test.xml" ; private static final String XPATH_FOR_PRM_MaxThread = "/config/param[@id='MaxThread']/text()"; public static void main(String[] args) { try { DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); docFactory.setNamespaceAware(true); DocumentBuilder builder = docFactory.newDocumentBuilder(); Document doc = builder.parse(CFG_FILE); Node param = XPathAPI.selectSingleNode( doc, XPATH_FOR_PRM_MaxThread ); if ( param instanceof Text ) { System.out.println( Integer.decode(((Text)(param)).getNodeValue() ) ); } } catch (Exception e) { e.printStackTrace(); } } } 

3.使用Java SE 1.4 + jdom + jaxen的JAXP 1.1标准部分

你需要添加这两个jar子(可从www.jdom.org获得 – 二进制文件,包括jaxen)。

 import java.io.File; import org.jdom.*; import org.jdom.input.SAXBuilder; import org.jdom.xpath.XPath; public class TestXPath { private static final String CFG_FILE = "test.xml" ; private static final String XPATH_FOR_PRM_MaxThread = "/config/param[@id='MaxThread']/text()"; public static void main(String[] args) { try { SAXBuilder sxb = new SAXBuilder(); Document doc = sxb.build(new File(CFG_FILE)); Element root = doc.getRootElement(); XPath xpath = XPath.newInstance(XPATH_FOR_PRM_MaxThread); Text param = (Text) xpath.selectSingleNode(root); Integer maxThread = Integer.decode( param.getText() ); System.out.println( maxThread ); } catch (Exception e) { e.printStackTrace(); } } } 

将XML文档转换为其他格式是XSLT的原因。 您可以使用XSLT输出HTML,JSON,另一个XML文档或您需要的任何其他内容。 您没有指定所需的输出类型。 如果你只是抓住一些元素的内容,那么也许你不想打扰XSLT。 除此之外,XSLT还提供了一个优雅的解决方案。 这主要是因为XSLT理解它正在处理的文档的结构。 它的处理模型是树遍历和模式匹配,这基本上就是你在Java中手动执行的操作。

您可以使用XSLT将源数据转换为您选择的表示forms。 您的代码将始终适用于此结构。 然后,当您正在使用的组织更改架构时,您只需更改XSLT即可将新XML转换为自定义格式。 您的其他代码都不需要更改。 您的业​​务逻辑为什么要关心其源数据的格式?

您是对的,XSLT基于基于规则的事件驱动方法的处理模型使您的代码对模式中的更改更具弹性。

因为它是与DOM一起使用的程序/导航方法的不同处理模型,所以有一种学习和熟悉曲线,有些人觉得这很令人沮丧; 如果你想这样做,请耐心等待,因为在想法点击之前会有一段时间。 一旦你在那里,它比DOM编程容易得多。

良好的XSLT处理器的性能将足以满足您的需求。 当然可以编写非常低效的代码,就像在任何语言中一样,但我很少看到XSLT是瓶颈的系统。 通常,XML解析比XSLT处理花费的时间更长(这与DOM或JAXB或其他任何东西的成本相同。)

正如其他人所说,很大程度上取决于你想对XML数据做些什么,你还没有真正解释过。

由于性能很重要,我建议使用SAX解析器。 JAXB将为您提供与DOM解析PLUS大致相同的性能,它将更容易和可维护。 如果您正在使用JAXB,那么处理模式中的更改也不会对您造成严重影响,只需获取新模式并重新生成类。 如果您在JAXB和域逻辑之间建立了桥梁,则可以在该层中吸收更改,而无需担心XML。 我更喜欢将XML视为消息传递层中使用的消息。 所有应用程序代码都应该与XML模式无关。