我使用这个XML源:
<?xml version="1.0" encoding="UTF-8"?>
<sets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="simulation-request.xsd">
<set>
<hP />
<para>
<setP>
<nom1>acc</nom1>
<nom2></nom2>
<typ>T</typ>
<oP>T_EQUALS</oP>
<val1>40</val1>
<bId>21</bId>
</setP>
</para>
<issuers />
</set>
<set>
<hP>
<sethP>
<hTyp>EX</hTyp>
<tFt>L_D</tFt>
<tFv>1</tFv>
<sCF>cd</sCF>
<setP>
<nom1>bount</nom1>
<oP>NLO</oP>
<val1>00</val1>
<bId>22</bId>
</setP>
<setP>
<nom1>bount</nom1>
<oP>NLO</oP>
<val1>00</val1>
<bId>23</bId>
</setP>
<setP>
<nom1>bount</nom1>
<oP>NLO</oP>
<val1>00</val1>
<bId>31</bId>
</setP>
</sethP>
</hP>
<para>
<setP>
<nom1>bount</nom1>
<nom2></nom2>
<typ>LO</typ>
<oP>T_C</oP>
<val1>1</val1>
<bId>24</bId>
</setP>
</para>
<issuers />
</set>
</sets>
使用这个XSLT源:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="no" xml:space="preserve"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/"><xsl:text> </xsl:text>
<xsl:for-each select="sets/set/hP | sets/set/para/setP">
<com-set-cond b.name="netInternalMs" name="{.//bId}">
</com-set-cond><xsl:text> </xsl:text>
</xsl:for-each>
</xsl:template>
输出是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<com-set-cond b.name="netInternalMs" name=""/>
<com-set-cond b.name="netInternalMs" name="21"/>
<com-set-cond b.name="netInternalMs" name="22"/>
<com-set-cond b.name="netInternalMs" name="24"/>
但预期的输出必须是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<com-set-cond b.name="netInternalMs" name="21"/>
<com-set-cond b.name="netInternalMs" name="22"/>
<com-set-cond b.name="netInternalMs" name="23"/>
<com-set-cond b.name="netInternalMs" name="31"/>
<com-set-cond b.name="netInternalMs" name="24"/>
其中,21、22、23、31和24的每个数字都是整个xml文件中元素bId的值,并且当像第一个标签这样的祖先中没有bId元素时,我的转换将不会显示任何内容,也不会显示一行"name"为空值的行作为使用我的转换后输出文件中的第一行有人知道怎么做吗?谢谢你的帮助。
问题出在xsl:for-each
<xsl:for-each select="sets/set/hP | sets/set/para/setP">
特别是sets/set/hPxpath。这将匹配两个hP元素。第一个是空的,因此生成了空的name属性。第二个包含三个setP元素,但执行name="{.//bId}"
只会拾取第一个(在这种情况下,bId=22)
因此,您可能需要将xsl:for-each更改为此
<xsl:for-each select="sets/set/hP/sethP/setP | sets/set/para/setP">
如果您不担心setP元素的级别,您可以将其简化为以下
<xsl:for-each select=".//setP">
请注意,通常使用xsl:apply-templates而不是xsl:for-each,因为这可以使代码更可读,减少缩进,并且更容易重用代码。
<xsl:template match="/">
<xsl:text> </xsl:text>
<xsl:apply-templates select=".//setP" />
</xsl:template>
<xsl:template match="setP">
<com-set-cond b.name="netInternalMs" name="{.//bId}" />
<xsl:text> </xsl:text>
</xsl:template>