2017-06-06 22 views
2

我期待从源xml中转换多个元素,并将它们合并到逗号分隔文本中的单个目标字符串元素中。多元素到扁平字符串变换

条件 源输入是布尔类型,只有当真正的价值应该被列入目标列表

例如XML

<Root-Element> 
<EnggTypes> 
<Engg1>true</Engg1> 
<Engg2>true</Engg2> 
<Engg3>false</Engg3> 
<Engg4>false</Engg4> 
<Engg5>true</Engg5> 
</EnggTypes> 
</Root-Element> 

预计变换

<Root-Element> 
<RoleTypes>Role1,Role2,Role5</RoleTypes> 
</Root-Element> 

展望实现XSL 1.0或2.0

我开始得太多,并试图使用一个变量在目标端,看我能不能做一些相同选择/何时使用以前的值构造字符串并进行连接,但似乎不起作用,因为变量值一旦设置就无法更改!

<xsl:variable name="roleVar"> 
<xsl:if test="Engg1/text()='true'">Role1</if> 
<xsl:if test="Engg2/text()='true'">concat(roleVar,",",Role2)</if> 
<xsl:if test="Engg3/text()='true'">concat(roleVar,",",Role3)</if> 
<xsl:if test="Engg4/text()='true'">concat(roleVar,",",Role4)</if> 
<xsl:if test="Engg5/text()='true'">concat(roleVar,",",Role5)</if> 
</xsl:variable> 

任何输入值得赞赏。

预先感谢

回答

2

可以选择的那些元件,并且在一个表达构建体的值:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="EnggTypes"> 
     <xsl:copy> 
      <xsl:value-of select="*[. = 'true']/concat('Role', replace(local-name(), '[^0-9]+', ''))" separator=","/> 
     </xsl:copy> 
    </xsl:template> 

</xsl:transform> 

http://xsltransform.net/bEzjRJR/1给出

<Root-Element> 
<EnggTypes>Role1,Role2,Role5</EnggTypes> 
</Root-Element> 
+0

这是什么构成第一个元素?没有它似乎也是一样的。 – miken32

+1

第一个模板是所谓的“身份”模板 - 它被称为“身份”,因为它只是复制任何匹配相同的东西,而不会改变它。没有身份模板,你不会得到相同的结果。使用Saxon-HE 9.6.0.7处理器并注释出身份模板,我得到''列表,但没有最外层的<标签对。 –

+0

感谢Martin,我正在探索模板,但只是没有找到我可以实现的正确方法。有时候,如果你不是超级样式表专家,那么像这样一个非常简单的映射可能会抢走你整整一天,我以为我一直呆到昨天,但学习永远不会停止。再次感谢! –

2

XSLT 1.0溶液:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 

    <xsl:template match="@* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="EnggTypes"> 
    <xsl:copy> 
     <RoleTypes> 
     <xsl:apply-templates select="*[starts-with(local-name(), 'Engg')][text() = 'true']"/> 
     </RoleTypes> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="*[starts-with(local-name(), 'Engg')][text() = 'true']"> 
    <xsl:value-of select="concat('Role', substring-after(local-name(), 'Engg'))"/> 

    <xsl:if test="position() != last()"> 
     <xsl:text>,</xsl:text> 
    </xsl:if> 
    </xsl:template> 

</xsl:stylesheet>