我想知道是否有人能够针对我目前正在努力解决的问题提出更多“pythonic”解决方案。
我有一个源XML文件,我正在编写一个XSLT生成器。源XML的相关部分如下所示:
...
<Notes>
<Note>
<Code>ABC123</Code>
<Text>Note text contents</Text>
...
</Note>
<Note>
...
</Note>
...
</Notes>
...
我有一些与此类似的对象:
from lxml.builder import ElementMaker
#This element maker has the target output namespace
TRGT = ElementMaker(namespace="targetnamespace")
XSL = ElementMaker(namespace="'http://www.w3.org/1999/XSL/Transform',
nsmap={'xsl':'http://www.w3.org/1999/XSL/Transform'})
#This is the relevant part of the 'generator output spec'
details = {'xpath': '//Notes/Note', 'node': 'Out', 'text': '{Code} - {Text}'}
目的是从'details'对象生成以下的XSLT片段:
<xsl:for-each select="//Notes/Note">
<Out><xsl:value-of select="Code"/> - <xsl:value-of select="Text"/></Out>
</xsl:for-each>
我遇到困难的部分是用XML节点替换{placeholder}文本。我最初尝试这样做:
import re
text = re.sub('\{([^}]*)\}', '<xsl:value-of select="\\1"/>', details['text'])
XSL('for-each',
TRGT(node, text)
select=details['xpath'])
但这会逃脱尖括号角色(即使它有效,如果我挑剔它意味着我很好地命名空间的ElementMakers被绕过,我不喜欢):
<xsl:for-each select="//Notes/Note">
<Out><xsl:value-of select="Code"/> - <xsl:value-of select="Text"/></Out>
</xsl:for-each>
目前我有这个,但感觉不是很好:
start = 0
note_nodes = []
for match in re.finditer('\{([^}]*)\}', note):
text_up_to = note[start:match.start()]
match_node = self.XSL('value-of', select=note[match.start()+1:match.end()-1])
start = match.end()
note_nodes.append(text_up_to)
note_nodes.append(match_node)
text_after = note[start:]
note_nodes.append(text_after)
XSL('for-each',
TRGT(node, *note_nodes)
select=details['xpath'])
是否有更好的方法(例如将正则表达式拆分为列表,然后将函数应用于匹配的元素)或者我只是过于挑剔?
谢谢!
答案 0 :(得分:1)
note_nodes=re.split(r'\{(.*?)\}',details['text'])
# ['', 'Code', ' - ', 'Text', '']
note_nodes=[n if i%2==0 else XSL('value-of',select=n)
for i,n in enumerate(note_nodes)]