我有一个xml(如下所示),其中如果一个节点(ref_name_1,ref_name_2,ref_name_3)包含一些文本,那么我们将使用xslt生成相应的节点,并在属性中为例如1,2等分配一个id号。我试图找出解决方案,但是没有发现任何与此相关的内容甚至没有在stackoverflow上,所以一点帮助都会非常明显。
示例XML
<?xml version="1.0" encoding="UTF-8"?>
<reference>
<ref_name_1>reference1</ref_name_1>
<ref_company_1>company1</ref_company_1>
<ref_position_1>position3</ref_position_1>
<ref_name_2 />
<ref_company_2>company2</ref_company_2>
<ref_position_2>position2</ref_position_2>
<ref_name_3>reference3</ref_name_3>
<ref_company_3>company3</ref_company_3>
<ref_position_3>position3</ref_position_3>
</reference>
预期产出:
<?xml version="1.0" encoding="UTF-8"?>
<services>
<service name="reference" id="1">
<name>reference1</name>
<company>company1</company>
<position>position1</position>
</service>
<service name="reference" id="2">
<name>reference3</name>
<company>company3</company>
<position>position3</position>
</service>
</services>
答案 0 :(得分:3)
关键是position()
功能。它适用于<xsl:for-each>
:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/reference">
<services>
<xsl:for-each select="*[starts-with(local-name(), 'ref_name_')][. != '']">
<xsl:variable name="originalNumber" select="substring-after(local-name(), 'ref_name_')"/>
<service name="reference" id="{position()}">
<name>
<xsl:value-of select="."/>
</name>
<company>
<xsl:value-of select="following-sibling::*[local-name()=concat('ref_company_', $originalNumber)][1]"/>
</company>
<position>
<xsl:value-of select="following-sibling::*[local-name()=concat('ref_position_', $originalNumber)][1]"/>
</position>
</service>
</xsl:for-each>
</services>
</xsl:template>
</xsl:stylesheet>
与<xsl:apply-tempaltes>
一样:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:template match="/reference">
<services>
<xsl:apply-templates select="*[starts-with(local-name(), 'ref_name_')][. != '']"/>
</services>
</xsl:template>
<xsl:template match="*[starts-with(local-name(), 'ref_name_')][. != '']">
<xsl:variable name="originalNumber" select="substring-after(local-name(), 'ref_name_')"/>
<service name="reference" id="{position()}">
<name>
<xsl:value-of select="."/>
</name>
<company>
<xsl:value-of select="following-sibling::*[local-name()=concat('ref_company_', $originalNumber)][1]"/>
</company>
<position>
<xsl:value-of select="following-sibling::*[local-name()=concat('ref_position_', $originalNumber)][1]"/>
</position>
</service> </xsl:template>
</xsl:stylesheet>
答案 1 :(得分:1)
还有xsl:number
,此处与for-each-group group-starting-with
一起使用:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="reference">
<services>
<xsl:for-each-group select="*" group-starting-with="*[starts-with(local-name(), 'ref_name_')]">
<xsl:if test="normalize-space()">
<service name="reference">
<xsl:attribute name="id">
<xsl:number count="*[starts-with(local-name(), 'ref_name_') and normalize-space()]"/>
</xsl:attribute>
<xsl:apply-templates select="current-group()"/>
</service>
</xsl:if>
</xsl:for-each-group>
</services>
</xsl:template>
<xsl:template match="reference/*">
<xsl:element name="{replace(local-name(), '^ref_|_[0-9]+$', '')}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:transform>