2011-09-22 59 views
0

我在想如果任何人都可以想出一個更「pythonic」的解決方案來解決我目前正在解決的問題。以xml節點替換文本的pythonic方式

我有一個源XML文件,我正在編寫一個XSLT生成器。源XML的相關部分看起來是這樣的:

... 
<Notes> 
    <Note> 
     <Code>ABC123</Code> 
     <Text>Note text contents</Text> 
     ... 
    </Note> 
    <Note> 
     ... 
    </Note> 
    ... 
</Notes> 
... 

而且我有一些對象anaologous這些:

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}'} 

目的是從「細節」對象產生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>&lt;xsl:value-of select="Code"/&gt; - &lt;xsl:value-of select="Text"/&gt;</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']) 

有沒有一種更好的方式(例如,以一個正則表達式分割成一個列表,然後將一個函數的元素whic h是比賽)還是我只是過分挑剔?

謝謝!

回答

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)] 
+0

Spot on。謝謝! – actionshrimp