带有内部属性的xpath可选属性

时间:2014-11-07 12:02:02

标签: xml xslt xpath

我有一个带有嵌套元素的xml是可选的,我必须使用层次结构中的属性创建一个csv文件,即使可选属性不存在。

这是xml数据文件:

    <dataroot xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://mycomp.com/test/xml/model">
    <ELEMENTS>
        <COUNTRY cod_cnt="030">
            <AS cod_as="030308">
             <CONTRACT num_CONTRACT="8715167"/>
             <CONTRACT num_CONTRACT="8715224"/>
            </AS>
         <AS cod_as="030309"/>
    </COUNTRY>
    </ELEMENTS>
</dataroot>

我需要具有AS标签的元素,即使它有合同也是如此。 我写过类似的东西,但我被困住了:

<xsl:for-each select="/doc:dataroot/doc:ELEMENTS/doc:COUNTRY/doc:AS/doc:CONTRACT">
    <xsl:value-of select="../../@cod_cnt"/>@<xsl:value-of select="../@cod_as"/>
    @<xsl:value-of select="@num_CONTRACT"/>@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@D<xsl:text> </xsl:text>
</xsl:for-each>

我知道我错过了一种联盟,但不能再进一步了。

我期待这个输出:

030@030308@8715167@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@D
030@030308@8715224@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@D
030@030309@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@D

注意前两行是我用附加的xls获得的输出,第三行是手写的,以显示我期望的输出。

1 个答案:

答案 0 :(得分:0)

如果您想保留for-each结构,下面的陈述应该适合您。您需要首先在doc:AS上进行迭代,然后在doc:CONTRACT上进行迭代(如果有的话)。

 <xsl:for-each select="/doc:dataroot/doc:ELEMENTS/doc:COUNTRY/doc:AS">
        <xsl:value-of select="../@cod_cnt"/><xsl:text>@</xsl:text><xsl:value-of select="@cod_as"/>
        <xsl:for-each select="doc:CONTRACT>
             <xsl:text>@</xsl:text><xsl:value-of select="@num_CONTRACT"/>
        </xsl:for-each>
        <xsl:text>@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@D</xsl:text>
    </xsl:for-each>

但是个人,我更喜欢使用模板匹配,这会在你的情况下给出类似的东西(未经测试):

<xsl:template match="/">
    <!-- Select the <doc:AS> if they are your 'rows' in the csv output -->
    <xsl:apply-template match="/doc:dataroot/doc:ELEMENTS/doc:COUNTRY/doc:AS"/>
</xsl:template>

<xsl:template match="doc:AS">
    <!-- Do the job for the doc:AS -->
    <xsl:value-of select="../@cod_cnt"/><xsl:text>@</xsl:text><xsl:value-of select="@cod_as"/>
    <!-- Call template for doc:Contract if any -->
    <xsl:apply-templates select="doc:Contract"/>
    <!-- Then add the end of your row -->
    <xsl:text>@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@0@D</xsl:text>
</xsl:template>

<xsl:template match="doc:CONTRACT">
    <!-- Do the job for doc:CONTRACT-->
    <xsl:text>@</xsl:text><xsl:value-of select="@num_CONTRACT"/>
</xsl:template>