0

我正在尝试使用应用模板从多个相似的父节点迭代特定的子节点。下面的例子:

<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>

现在,我想在国家元素下的所有 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 元素匹配项,但事实并非如此。在这里需要一些帮助。

4

2 回答 2

3

尝试以下脚本:

<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

<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="//literacyRates"/>
  </xsl:template>

  <xsl:template match="literacyRates">
    <xsl:text>list=</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&#xA;</xsl:text>
  </xsl:template>

</xsl:stylesheet>
于 2017-07-05T18:53:41.423 回答
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>
    

    仅当您在处理流程的早期使用时,该match属性才会执行任何操作。apply-templates由于您只使用过call-template,因此该match属性什么也不做。
    此外,由于match属性指定literacyRate,但您的输入 XML 只有literacyRates元素,即使您之前使用过,这仍然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>

打破这一点,我们有:

  • <xsl:output method="text"/>指定我们输出的是文本,而不是 XML。这可能会影响输出格式,具体取决于您的 XSL 处理器。
  • <xsl:strip-space elements="*"/>防止源 XML 和 XSL 中的空格(即缩进)影响输出中的空格。
  • <xsl:apply-templates select="country//literacyRates"/>to apply-templates,并且特别是select仅那些是literacyRates元素后代的country元素。

假设

这假设每个<country>元素只有一个 <literacyRates>后代元素。如果有多个这样的元素,输出将变得混乱——每个值列表都将附加到输出字符串中,可能会导致输出行如list=25,36,4345,46,55,56(两个列表混合在一起,中间没有任何内容)。

一种工作方法:XML 输出

上面的文本输出有些有损和混乱——我们不知道哪个列表属于哪个国家,多<literacyRates>合一<country>会产生损坏的输出。

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

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="countries">
        <SampleOutput>
            <xsl:apply-templates select="country//literacyRates"/>
        </SampleOutput>
    </xsl:template>

    <xsl:template match="literacyRates">
        <literacyRates>
            <xsl:attribute name="country" select="ancestor::country/@name"/>
            <xsl:attribute name="type" select="name(..)"/>
            <xsl:value-of select="."/>
        </literacyRates>
    </xsl:template>

</xsl:stylesheet>
于 2017-07-05T19:42:43.917 回答