尝试进行此转换,但无法在网络或文档中找到答案(此处为newbe)。
试着做这样的事情:
<Info>
<Type p="1">MyType1</Type>
<Type p="2">MyType2</Type>
<Type p="3">MyType3</Type>
<Values>
<r p="1">MyValue1</r>
<r p="2">MyValue2</r>
<r p="3">MyValue3</r>
</Values>
</Info>
显示为这样的纯文本转换:
MyType1;MyValue1
MyType2;MyValue3
MyType3;MyValue3
作为输出的两个字段由“p”属性连接¿是否可能?
答案 0 :(得分:4)
XSLT有a built-in mechanism for handling cross-references;最好使用它:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text" encoding="UTF-8" />
<xsl:key name="value" match="r" use="@p" />
<xsl:template match="/Info">
<xsl:for-each select="Type">
<xsl:value-of select="."/>
<xsl:text>;</xsl:text>
<xsl:for-each select="key('value', @p)">
<xsl:value-of select="."/>
<xsl:if test="position()!= last()">
<xsl:text>;</xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="position()!= last()">
<xsl:text> </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
假设:
Type
条目都是唯一的; 可能有多个具有相同类型的值;例如,以下输入:
<Info>
<Type p="1">MyType1</Type>
<Type p="2">MyType2</Type>
<Type p="3">MyType3</Type>
<Values>
<r p="1">MyValue1</r>
<r p="2">MyValue2a</r>
<r p="2">MyValue2b</r>
<r p="3">MyValue3</r>
</Values>
将返回:
MyType1;MyValue1
MyType2;MyValue2a;MyValue2b
MyType3;MyValue3
答案 1 :(得分:1)
一种可能的解决方案是使用匹配Type
的模板打印Type
的值,后跟相应r
元素的值和匹配Values
的空模板避免像这样两次打印Values
:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="text" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:strip-space elements="*"/>
<xsl:template match="Type">
<xsl:variable name="current" select="@p"/>
<xsl:value-of select="."/>
<xsl:value-of select="concat(';',//Values/r[@p=$current])"/>
<xsl:if test="position() != last()">
<xsl:text>
</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="Values"/>
</xsl:transform>
应用于您的输入,生成以下输出:
MyType1;MyValue1
MyType2;MyValue2
MyType3;MyValue3
答案 2 :(得分:1)
这是一个相当简单的方法
<xsl:template match="/">
<xsl:variable name="newline">
<xsl:text>
</xsl:text>
</xsl:variable>
<xsl:for-each select="/Info/Type" >
<xsl:variable name="p" select="@p" />
<xsl:value-of select="." />
<xsl:text>;</xsl:text>
<xsl:value-of select=" /Info/Values/r[@p=$p] " />
<xsl:if test=" position() != last() ">
<xsl:value-of select="$newline" />
</xsl:if>
</xsl:for-each>
</xsl:template>
这将为每个Type节点仅选择第一个匹配的Values / r节点。因此,假设应忽略具有相同@p的任何其他值/ r节点。
答案 3 :(得分:1)
使用这个简单而简短的XSLT 1.0解决方案:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kRByP" match="r" use="@p"/>
<xsl:template match="Type/text()">
<xsl:value-of select="concat(.,';',key('kRByP', ../@p), '
')"/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
在提供的源XML文档上应用此转换时:
<Info>
<Type p="1">MyType1</Type>
<Type p="2">MyType2</Type>
<Type p="3">MyType3</Type>
<Values>
<r p="1">MyValue1</r>
<r p="2">MyValue2</r>
<r p="3">MyValue3</r>
</Values>
</Info>
产生了想要的正确结果:
MyType1;MyValue1
MyType2;MyValue2
MyType3;MyValue3
<强>解释强>:
p
属性的值唯一标识此属性所属的r
或Type
元素