在未指定出现顺序时处理 XSLT 中的子标记

Posted

技术标签:

【中文标题】在未指定出现顺序时处理 XSLT 中的子标记【英文标题】:handling the child tags in XSLT when the order of occurance is not specified 【发布时间】:2012-05-01 22:21:29 【问题描述】:

我正在处理 XSLT 转换。我有一个源文件,其中有一些名为 tag 的标签。

认为我的源 xml 是这样的。

<ABC>
    <Name>Some Name </Name>
    <ID>Some ID</ID>
    <Address>Some Address</Address>
    <Place>Some Place</Place>
    <ID>Some ID</ID>
    <Name>Some Name </Name>
    <Name>Some Name </Name>     

</ABC>

规则:

  ABC is parent Tag which has 4 child tags. Name, ID, Address, Place. 
  These child tags can occur many times and in any ordrer.
  Upon reading the tag , I want to change the name of the tag, and do some processing on the value present in the tag.
  The input XML may have child tags in any order, and many times.
  I want to write a common XSLT which will read the child tags in the order in which they occur, and display them as given under.

我想这样显示输出。

        <Frame:Name>
                   <text>Some Name</text>
        </Frame:Name>
   <Frame:ID>
                   <text>Some ID</text>
        </Frame:ID>
        <Frame:ADdrress>
                   <text>Some Address</text>
        </Frame:Address>
        <Frame:Place>
                   <text>Some Place</text>
        </Frame:Place>
   <Frame:ID>
                   <text>Some ID</text>
        </Frame:ID>
       <Frame:Name>
                   <text>Some Name</text>
        </Frame:Name>
       <Frame:Name>
                   <text>Some Name</text>
        </Frame:Name>

我完全震惊了它是如何做到的。

如果源 XML 中子元素的出现顺序发生变化,它也应该反映在输出 XML 中。

有人可以分享评论吗?

谢谢。

【问题讨论】:

你能分享你的 XSLT 代码吗?如果它看起来不错,那么我们可以根据您的要求进行修改。我们可以设计新代码,但如果您发布代码,您就可以知道自己的错误 在想要的结果中,您错过了最后一个 Name 元素。请正确。 【参考方案1】:

解决此类问题的 XSLT 方法是使用模板。结果是更简单、更短且易于理解的代码,通常没有任何xsl:choosexsl:whenxsl:otherwisexsl:ifxsl:for-each

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:Frame="some:undefined namespace">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:template match="/*">
   <t><xsl:apply-templates/></t>
 </xsl:template>

 <xsl:template match="*/*">
     <xsl:element name="Frame:name()" namespace="some:undefined namespace">
       <text><xsl:apply-templates /></text>
     </xsl:element>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时

<ABC>
    <Name>Some Name </Name>
    <ID>Some ID</ID>
    <Address>Some Address</Address>
    <Place>Some Place</Place>
    <ID>Some ID</ID>
    <Name>Some Name </Name>
    <Name>Some Name </Name>
</ABC>

产生想要的正确结果

<t xmlns:Frame="some:undefined namespace">
   <Frame:Name>
      <text>Some Name </text>
   </Frame:Name>
   <Frame:ID>
      <text>Some ID</text>
   </Frame:ID>
   <Frame:Address>
      <text>Some Address</text>
   </Frame:Address>
   <Frame:Place>
      <text>Some Place</text>
   </Frame:Place>
   <Frame:ID>
      <text>Some ID</text>
   </Frame:ID>
   <Frame:Name>
      <text>Some Name </text>
   </Frame:Name>
   <Frame:Name>
      <text>Some Name </text>
   </Frame:Name>
</t>

【讨论】:

感谢您提供的信息。我可以对每个元素的数据进行一些操作吗?因为,它直接改变了标签的名称。请澄清。 @muzimil:是的,在匹配模板中可以执行任何额外的处理。请为您的新问题提出一个新问题。当前的问题有一个完整的解决方案——正如这个答案中所提供的那样。 我想在每个标签中捕获文本并调用其他模板。你能说如果可能的话,我会提出一个问题。 @muzimil:请使用新要求编辑问题并显示相应的所需结果——或者,更好,提出一个新问题。是的,这是可能的。 XSLT 是图灵完备的语言,可用于实现任何算法。【参考方案2】:

根据 jeevan 的建议。

  <xsl:template match="ABC" >
    <ABC>
        <xsl:for-each select ="child::*">
        <xsl:choose>
          <xsl:when test="name()='Name'">
            <xsl:element name="Frame:Name">
              <xsl:apply-templates  select="."/>
           </xsl:element>
          </xsl:when>

          <xsl:when test="name()='ID'">
            <Frame:ID>
              <xsl:apply-templates select="."/>
            </Frame:ID>
          </xsl:when>
            <xsl:when test="name()='Address'">
            <Frame:Address>
              <xsl:apply-templates select="."/>
            </Frame:Address>
          </xsl:when>

          <xsl:when test="name()='Place'">
            <Frame:Place>
              <xsl:apply-templates select="."/>
            </Frame:Place>
          </xsl:when>
     </xsl:choose>
      </xsl:for-each>

【讨论】:

您可能有兴趣看到一个缩短三倍的解决方案 :) 可怕的代码。永远不要使用 xsl:choose 打开元素名称。这就是模板规则的用途。

以上是关于在未指定出现顺序时处理 XSLT 中的子标记的主要内容,如果未能解决你的问题,请参考以下文章

是否未指定在未评估的上下文中实例化模板/lambda?

在SQL语句中用PARALLEL指定并行查询,应该怎么用

如何指定处理器关联?

XTDE0160:XSLT 1.0 兼容模式在此配置中不可用,在未命名模式下 /invoice:request 的内置模板规则中

java.lang.RuntimeException:无法在未调用 Looper.prepare() 的线程内创建处理程序,在 android 中出现运行时错误

在比较 XSLT <xsl:if> 中的字符串时,如何指定“不等于”?