【问题标题】:XSLT: Get all children of parents with specified attributesXSLT:获取具有指定属性的父母的所有孩子
【发布时间】:2015-08-26 21:33:28
【问题描述】:

鉴于此 XML:

<?xml version="1.0" encoding="iso-8859-2" ?>
<r>
    <products start="5" stop="8">
        <p>
            <id> 50 </id>
            <name> Murphy </name>
            <price> 33 </price>
        </p>
        <p>
            <id> 10 </id>
            <name> Margarethe </name>
            <price> 11 </price>
        </p>
    </products>
    <products start="1" stop="4">
        <p>
            <id> 555 </id>
            <name> XXXX</name>
            <price> 333 </price>
        </p>
        <p>
            <id> 10 </id>
            <name> Mexico </name>
            <price> 11 </price>
        </p>
    </products>
    <products start="1" stop="4">
        <p>
            <id> 30 </id>
            <name> HKoney </name>
            <price> 11 </price>
        </p>
        <p>
            <id> 10 </id>
            <name> HMargarethe </name>
            <price> 11 </price>
        </p>
    </products>
</r>

使用此 XSL:

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

<xsl:template match="products[@start &lt; 2 and @stop &gt; 2]" >
    <xsl:call-template name="test"/>
</xsl:template>

<xsl:template name="test">
     <test><xsl:value-of select="*/name"/></test>
</xsl:template>

<xsl:template match="products"/>

</xsl:stylesheet>

有这个输出:

<?xml version="1.0" encoding="UTF-8"?>
<test> XXXX</test>
<test> HKoney </test>

问:为什么我没有得到所有具有指定属性的父级的&lt;p&gt;,只有第一个? MexicoHMargarethe 也是预期的。


期望的输出:

<?xml version="1.0" encoding="UTF-8"?>
<test> XXXX</test>
<test> Mexico </test>
<test> HKoney </test>
<test> HMargerethe</test>

注意:我希望它在没有 for-each 循环的情况下工作。

【问题讨论】:

  • 您希望单个

    元素中的所有名称都出现在 中吗?请提供所需输出的示例

  • 我已经输入了想要的输出。

标签: xslt transform


【解决方案1】:

您可以尝试在&lt;name&gt; 元素上直接使用apply-templates

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

    <xsl:template match="products[@start &lt; 2 and @stop &gt; 2]" >
        <xsl:apply-templates select="p/name"/>
    </xsl:template>

    <xsl:template match="name">
        <test>
            <xsl:value-of select="."/>
        </test>
    </xsl:template>

    <xsl:template match="products"/>

</xsl:stylesheet>

【讨论】:

    【解决方案2】:

    您必须处理所有p 元素,请参阅此处的xsl:for-each

    <xsl:template name="test">
        <test>
            <xsl:for-each select="*">
                <xsl:value-of select="name"/>
            </xsl:for-each>
        </test>
    </xsl:template>
    

    【讨论】:

    • 感谢您的回答,但我忘了说明我不想让for-eac h 参与
    • for-each有什么问题?我只是好奇。顺便说一句,您的输出示例不是有效的 XML 文件,因为它不包含其根元素。
    【解决方案3】:

    问:为什么我没有得到所有具有指定属性的父级的&lt;p&gt;,只有第一个? MexicoHMargarethe 也是预期的。

    注意模板test 只为每个products 元素调用一次:

    <xsl:template match="products[@start &lt; 2 and @stop &gt; 2]" >
        <xsl:call-template name="test"/>
    </xsl:template>
    

    每次调用模板时,您都会拉取多个name 元素以供&lt;xsl:value-of&gt; 处理。根据 MSDN 关于&lt;xsl:value-of&gt;select 属性:

    必填。要针对当前上下文评估的表达式 (XML)。结果被转换为字符串,就像调用 string() 函数一样。 通过在集合中插入第一个节点的字符串值,将节点集转换为字符串

    规范也讲述了同样的故事,请参阅 W3C xslt value-ofxpath function string()

    【讨论】:

      【解决方案4】:

      修改了代码不使用for循环

      请使用下面的代码,它按预期工作

      <?xml version="1.0" encoding="UTF-8"?>
      <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:template match="/" name ="ParentCopy">
      <xsl:param name="LoopCountA">1</xsl:param>
      <xsl:variable name = "Count" >
              <xsl:value-of select = "count(r/products)"/>
          </xsl:variable>
          <xsl:choose>
          <xsl:when test ="($LoopCountA  &lt;= $Count) ">
      <xsl:choose>
                  <xsl:when test ="r/products[$LoopCountA][@start &lt; 2 and @stop &gt; 2]">
                      <test>
          <xsl:value-of select = "r/products[$LoopCountA]/p[1]/name"/>
                      </test> 
      <test>
                          <xsl:value-of select = "r/products[$LoopCountA]/p[2]/name"/>
      </test>
                  </xsl:when>
      </xsl:choose>
          <xsl:call-template name="ParentCopy">
                  <xsl:with-param name="LoopCountA">
      <xsl:value-of select="$LoopCountA + 1"/>
                  </xsl:with-param>
      </xsl:call-template>
      </xsl:when>
      </xsl:choose>
      </xsl:template>
      

      </xsl:stylesheet>
      

      如有任何其他疑问,请告诉我

      【讨论】:

      • 寻找没有for-each的解决方案
      • 不幸的是,该主题已关闭并已解决:)。如需进一步通知,请尝试谷歌搜索 node-set() 函数,它非常有帮助。你也可以用@ 写用户名,比如@sreevathsa a
      • @Dajilido,谢谢你的信息。但在不使用 for-each 循环的情况下,上述 xsl 将如何按预期工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-29
      • 1970-01-01
      • 1970-01-01
      • 2018-03-18
      • 2021-12-02
      • 2019-05-02
      • 2013-11-23
      相关资源
      最近更新 更多