我们有会 Ruby、Python、.Net 或 Java 的开发人员。我们正在开发一个主要处理 XML 文档的应用程序。大部分工作是将预定义的 XML 文件转换为数据库表,通过数据库提供 XML 文档之间的映射,并从数据库创建报告等。哪种语言最容易且最快速地完成这项工作?(这是一个 web 应用程序)
这里使用动态语言规则。为什么呢?因为映射很容易编码和更改,无需重新编译和重建。
实际上,只要稍微聪明一点,您就可以将“XML XPATH到标记 -> DB表字段”的映射作为Python代码的不连续块导入到主应用程序中。
Python代码块是您的配置文件。它不是描述配置的.ini
文件或.properties
文件,而是是配置本身。
我们使用Python、xml.etree和SQLAlchemy(将SQL从程序中分离出来)进行此操作,因为我们可以轻松快速地启动,并具有极大的灵活性。
source.py
"""A particular XML parser. Formats change, so sometimes this changes, too."""
import xml.etree.ElementTree as xml
class SSXML_Source( object ):
ns0= "urn:schemas-microsoft-com:office:spreadsheet"
ns1= "urn:schemas-microsoft-com:office:excel"
def __init__( self, aFileName, *sheets ):
"""Initialize a XML source.
XXX - Create better sheet filtering here, in the constructor.
@param aFileName: the file name.
"""
super( SSXML_Source, self ).__init__( aFileName )
self.log= logging.getLogger( "source.PCIX_XLS" )
self.dom= etree.parse( aFileName ).getroot()
def sheets( self ):
for wb in self.dom.getiterator("{%s}Workbook" % ( self.ns0, ) ):
for ws in wb.getiterator( "{%s}Worksheet" % ( self.ns0, ) ):
yield ws
def rows( self ):
for s in self.sheets():
print s.attrib["{%s}Name" % ( self.ns0, ) ]
for t in s.getiterator( "{%s}Table" % ( self.ns0, ) ):
for r in t.getiterator( "{%s}Row" % ( self.ns0, ) ):
# The XML may not be really useful.
# In some cases, you may have to convert to something useful
yield r
model.py
"""This is your target object.
It's part of the problem domain; it rarely changes.
"""
class MyTargetObject( object ):
def __init__( self ):
self.someAttr= ""
self.anotherAttr= ""
self.this= 0
self.that= 3.14159
def aMethod( self ):
"""etc."""
pass
builder_today.py 是众多映射配置之一。
"""One of many builders. This changes all the time to fit
specific needs and situations. The goal is to keep this
short and to-the-point so that it has the mapping and nothing
but the mapping.
"""
import model
class MyTargetBuilder( object ):
def makeFromXML( self, element ):
result= model.MyTargetObject()
result.someAttr= element.findtext( "Some" )
result.anotherAttr= element.findtext( "Another" )
result.this= int( element.findtext( "This" ) )
result.that= float( element.findtext( "that" ) )
return result
loader.py
"""An application that maps from XML to the domain object
using a configurable "builder".
"""
import model
import source
import builder_1
import builder_2
import builder_today
# Configure this: pick a builder is appropriate for the data:
b= builder_today.MyTargetBuilder()
s= source.SSXML_Source( sys.argv[1] )
for r in s.rows():
data= b.makeFromXML( r )
# ... persist data with a DB save or file write
要进行更改,您可以更正构建器或创建新的构建器。您可以调整加载程序源以确定将使用哪个构建器。您可以很容易地将构建器的选择作为命令行参数。动态语言中的动态导入似乎对我来说过于繁琐,但它们非常方便。
为了快速完成,我发现 Groovy非常有用。
<Export>
<Product>
<SKU>403276</SKU>
<ItemName>Trivet</ItemName>
<CollectionNo>0</CollectionNo>
<Pages>0</Pages>
</Product>
</Export>
你可以简单地解析:
FIELDS = %w[SKU ItemName CollectionNo Pages]
doc = Hpricot.parse(File.read("my.xml"))
(doc/:product).each do |xml_product|
product = Product.new
for field in FIELDS
product[field] = (xml_product/field.intern).first.innerHTML
end
product.save
end
看起来你的应用程序非常适合使用Rails应用程序,你可以快速原型化所需内容,直接与所选数据库进行交互,并以任何需要的方式输出数据。
这是另一个很棒的资源页面使用Hpricot解析XML,可能会有帮助,还有文档。
使用LiNQ to XML,可以使用C#或VB.Net轻松实现。LiNQ to XML非常强大且易于实现。
ECMAScript可以使用E4X("ECMAScript for XML")很好地处理XML。这可以在Adobe的最新版本的ActionScript 3中看到。我相信JavaScript 2(我认为将与Firefox 4一起发布)也将支持E4X。
不确定独立的JavaScript解释器(即Rhino等)是否支持此功能,这可能是您最关心的问题...但如果它对您有用,请随时查找它们对其的支持情况(并向我们报告:-))。
请参见http://en.wikipedia.org/wiki/E4X#Example以获取简单示例。