XSLT按名称选择当前节点的所有第3级子级

时间:2017-07-05 17:50:47

标签: xml xslt child-nodes

我正在尝试使用apply-templates从多个类似的父节点迭代特定的子节点。示例如下:

<test_report 
xmlns:gml="http://www.opengis.net/gml" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<countries>
    <country name='sample1'>
        <education>
            <men>
                <literacyRates>25,36,43</literacyRates>
            </men>
        </education>
    </country>
    <country name='sample2'>
        <education>
            <men>
                <literacyRates>45,46,55,56</literacyRates>
            </men>
        </education>
    </country>
</countries>

现在,我想在所有属于countries元素的literacyRates元素上应用模板。我尝试了下面的XSL:

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

<xsl:template match="countries">
            <xsl:call-template name="countries" />   
</xsl:template>

<xsl:template name="countries" match="literacyRate">
        <xsl:call-template name="testoutput"><xsl:with-param name="list" select="." /> </xsl:call-template>
    ]
</xsl:template>

<xsl:template name="testoutput">
        <xsl:param name="list" select="."/>
    list=<xsl:value-of select="$list" />
</xsl:template>    

我原本期望以list=开头的输出行出现两次,因为我们有两个literacyRate元素匹配,但事实并非如此。需要一些帮助。

2 个答案:

答案 0 :(得分:3)

尝试以下脚本:

curl -H "Content-Type: application/json" -X POST -d '"{\"id\":\"2773\",\"countryCode\":\"US\",\"orderAmt\":\"100\"}"' http://localhost:9090
curl -H "Content-Type: application/json" -X POST -d '"{\"id\":\"2774\",\"countryCode\":\"CA\",\"orderAmt\":\"125\"}"' http://localhost:9090
curl -H "Content-Type: application/json" -X POST -d '"{\"id\":\"2775\",\"countryCode\":\"US\",\"orderAmt\":\"110\"}"' http://localhost:9090

或另一种解决方案,如果真的需要使用<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <xsl:template match="country//literacyRates"> <xsl:text>list=</xsl:text> <xsl:value-of select="."/> <xsl:text>&#xA;</xsl:text> </xsl:template> </xsl:stylesheet>

apply-templates

答案 1 :(得分:1)

现有的XSL代码

您的XSL存在许多问题。

  • 您使用call-template的方式没有多大意义。使用apply-templates会更加惯用。

  • 您有三个模板,但实际上只在最后一个模板中执行任何操作 - 而且只输出<countries>元素的字符串值。也可以只有一个模板:

    <xsl:template match="countries">
        list=<xsl:value-of select="."/>
    </xsl:template>  
    

    (我假设您的第二个模板中的换行符和]结束括号是错误的。)

  • 您的第二个模板同时具有name属性和match属性。

    <xsl:template name="countries" match="literacyRate">
          <xsl:call-template name="testoutput"><xsl:with-param name="list" select="." /> </xsl:call-template>
        ]
    </xsl:template>
    

    如果您在处理流程中使用matchapply-templates属性只会执行任何操作。由于您只使用call-templatematch属性不执行任何操作 此外,由于match属性指定literacyRate,但您的输入XML只有literacyRates个元素,因此仍然不会执行任何操作,即使您使用{ {1}}早些时候。

一种工作方法:文本输出

您希望每个apply-templates元素都有一个list=行。要将此输出生成为直接文本,以下操作:

<country>

打破这种局面,我们有:

  • <?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output method="text"/> <xsl:strip-space elements="*"/> <xsl:template match="countries"> <xsl:apply-templates select="country//literacyRates"/> </xsl:template> <xsl:template match="literacyRates"> <xsl:text>list=</xsl:text> <xsl:value-of select="."/> <xsl:text>&#10;</xsl:text> </xsl:template> </xsl:stylesheet> 指定我们输出的是文本,而不是XML。这可能会影响输出格式,具体取决于您的XSL处理器。
  • <xsl:output method="text"/>防止源XML和XSL中的空格(即缩进)影响输出中的空格。
  • <xsl:strip-space elements="*"/><xsl:apply-templates select="country//literacyRates"/>,以及具体apply-templatesselectliteracyRates元素后代的元素。

假设

这假设每个country元素只有一个 <country>后代元素。如果有多个这样的元素,输出将变得混乱 - 每个值列表将被附加到输出字符串,可能导致输出行像<literacyRates>(其中两个列表被一起排列,两者之间没有任何内容)

一种工作方法:XML输出

上面的文字输出有些有些混乱 - 我们不知道哪个列表属于哪个国家/地区,而list=25,36,4345,46,55,56中的多个<literacyRates>会产生损坏的输出。

这是生成XML的替代输出,包含更多信息。

<country>