2017-06-13 65 views
0

我是XSLT的新手,我有一个从csv文件转换而来的XML,如下所示,通过文本打开和关闭行distict,值。所有客房都在同一个记录标签, 有区别只在字符串值本身使用xslt转换创建一个带页眉和页脚的xsl转换xml到另一个xml

<?xml version="1.0" encoding="utf-8"?> 
<Items> 
<Row> 
    <Transaction>Open</Transaction> 
</Row> 
<Row> 
    <Transaction>Type plus</Transaction> 
</Row> 
<Row> 
    <Transaction>A</Transaction> 
</Row> 
<Row> 
    <Transaction>B</Transaction> 
</Row>  
<Row> 
    <Transaction>Close</Transaction> 
</Row> 
<Row> 
    <Transaction>Open</Transaction> 
</Row> 
<Row> 
    <Transaction>Type minus</Transaction> 
</Row> 
<Row> 
    <Transaction>C</Transaction> 
</Row> 
<Row> 
    <Transaction>D</Transaction> 
</Row>  
<Row> 
    <Transaction>Close</Transaction> 
</Row> 
... 
... 
... 
... 
... 
</Items> 

我想要的结果看作为following.I使用变量来存储使用可变“类型”,用于存储尝试加号或减号,但似乎我不能更新变量。任何人都可以创建一个可以完成以下转换的xsl。

<?xml version="1.0" encoding="utf-8"?> 
<result> 
<message> 
    <to>plus</to> 
    <from>A</from> 
</message> 
<message> 
    <to>plus</to> 
    <from>B</from> 
</message> 
<message> 
    <to>minus</to> 
    <from>C</from> 
</message> 
<message> 
    <to>minus</to> 
    <from>D</from> 
</message> 
... 
... 
... 
</result> 
+1

您可以使用XSLT 2.0处理器,如Saxon 9,XmlPrime,Alto VA? –

+1

另外,你是否真的希望输出是几个没有根元素的顶级'message'元素的片段? –

+1

如果你展示了一个格式良好的XML输入片段,当前所有这些'Transaction'元素都没有正确关闭,这也会有所帮助。 –

回答

1

这个例子很模糊;我们在这里需要的是一些明确的规则。

如果我们假定每个组的开始<Transaction>Open</Transaction> S IN,第二包含的类型,最后一个关闭的组,我们可以这样做:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:key name="grp" match="Row[not(Transaction='Open')]" use="generate-id(preceding-sibling::Row[Transaction='Open'][1])" /> 

<xsl:template match="Items"> 
    <result> 
     <xsl:for-each select="Row[Transaction='Open']"> 
      <xsl:variable name="group" select="key('grp', generate-id())" /> 
      <xsl:variable name="type" select="substring-after($group[1]/Transaction, 'Type ')" /> 
      <xsl:for-each select="$group[position() != 1 and position() != last()]">    
       <message> 
        <to> 
         <xsl:value-of select="$type"/> 
        </to> 
        <from> 
         <xsl:value-of select="Transaction"/> 
        </from> 
       </message> 
      </xsl:for-each> 
     </xsl:for-each> 
    </result> 
</xsl:template> 

</xsl:stylesheet> 

获得:

<?xml version="1.0" encoding="UTF-8"?> 
<result> 
    <message> 
    <to>plus</to> 
    <from>A</from> 
    </message> 
    <message> 
    <to>plus</to> 
    <from>B</from> 
    </message> 
    <message> 
    <to>minus</to> 
    <from>C</from> 
    </message> 
    <message> 
    <to>minus</to> 
    <from>D</from> 
    </message> 
</result> 
+0

谢谢@ michael.hor257k您的意见。你非常接近我需要的解决方案。我忘了在xml中添加一些信息。带有事务标记的incomng行表示打开了一些其他文本,但“打开”子字符串的位置始终相同。 Simalarly为具有接近子字符串的事务思考类似于Row [not(Transaction ='Open')]寻找类似substring的东西(Transaction,4,4) –

+0

因此,使用'substring(Transaction,4)='Open' '交易='打开'。 –

+0

太棒了!非常感谢@ michael.hor257k你节省了大量的挫折,长时间试图弄清楚这一点。 –