【问题标题】:Product Same Output XML using XSLT for different input XML formats使用 XSLT 为不同的输入 XML 格式产品相同的输出 XML
【发布时间】:2015-07-16 04:59:04
【问题描述】:

输入的 XML 可能是以下形式之一:

示例 1:

<studentRequest>
  <student> 
      <name>name</name>  
      <address>      
         <state>stateName</state>
         <city>cityName</city>
         <pin>123456</pin>
      </address>
       <no>123</no> 
    </student>
</studentRequest>

示例 2

<studentRequest>
  <student>         
      <address>
         <city>cityName</city>
         <pin>123456</pin>
         <state>stateName</state>
      </address>
      <name>name</name>
      <no>123</no>
</student>
</studentRequest>

期望的输出:

<studentRequest>
    <student>
      <address>
         <city>cityName</city>
         <pin>123456</pin>
         <state>stateName</state>
      </address>
      <name>name</name>
      <no>123</no>
    </student>
</studentRequest>

我写的 XSLT 如下

<xsl:template match="/">
 <studentRequest>
       <xsl:if test="student">
         <xsl:element name="student">
           <xsl:if test="student/name">
            <xsl:element name="name">
                <xsl:value-of select="student/name"/>
            </xsl:element>
           </xsl:if>
           <xsl:if test="student/no">
            <xsl:element name="no">
                <xsl:value-of select="student/no"/>
            </xsl:element>
           </xsl:if>
            <xsl:if test="student/address">
            <xsl:element name="address">
                ............
                ...............
            </xsl:element>
           </xsl:if>
           </xsl:element>
         </xsl:if>
       </xsl:template>
 </studentRequest>
</xsl:template>

这意味着如果输入的 XML 表单也发生了变化,我需要使用 XSLT 生成相同的输出。如果请求很小,我们可以像上面那样编写 XSLT,但是如果请求很大,那么是否有任何替代解决方案。提前致谢。

【问题讨论】:

  • 请注意,&lt;xsl:element&gt; 始终是不必要的除非您要设置计算元素名称。 &lt;xsl:element name="student"&gt; 是评估者复杂的说法 &lt;student&gt;
  • 您犯了一个典型的错误,即尝试使用单个示例指定您的需求,然后告诉我们该示例不足以解释完整的需求。从更好的需求声明重新开始。决定输出中元素顺序的规则是什么?
  • @MichaelKay 实际上原始示例非常大,所以我为此创建了小示例。这里没有规则。实际上,我们正在形成 WSIL 文件中存在的 SOAP 请求。为此,我们得到xml文件有不同的形式。但最后我们需要根据WSIL形成请求。你明白我说的吗?对不起我的英语不好。
  • 如果没有规则来确定输出的顺序,那么就没有办法编写程序以正确的顺序产生输出。

标签: xml xslt xpath


【解决方案1】:

您似乎在以某种方式对孩子进行排序,但除此之外您只想复制它们。

进行此类转换的方法总是这样:

  • 从身份模板开始
  • 只为要修改的节点编写模板

这样

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output indent="yes" />
  <xsl:strip-space elements="*" />

  <xsl:template match="node() | @*">
    <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="student">
    <xsl:copy>
      <xsl:apply-templates select="address" />
      <xsl:apply-templates select="name" />
      <xsl:apply-templates select="no" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="address">
    <xsl:copy>
      <xsl:apply-templates select="city" />
      <xsl:apply-templates select="pin" />
      <xsl:apply-templates select="state" />
    </xsl:copy>
  </xsl:template>

</xsl:transform>

【讨论】:

  • 请求很小,所以这个解决方案没有问题。如果请求很大,还有其他解决方案
  • 不知道你说的“问题”和“替代方案”是什么意思?以上有什么问题?
  • 上面的代码是 100% 正确的。我同意这一点。但是如果请求包含一个 XML,比如它包含 1000 行,那么编写这种类型的 XSLT 会很复杂。上面我给出了示例 XML
  • @DanielHaley 谢谢,我也打算这么建议。 :) 但它仍然是创可贴,IMO。
  • @PSR - 是的,你是对的,这就是身份模板。它将复制所有节点(属性、元素、文本、注释和处理指令)不变。 (除非节点的处理被具有更高优先级的模板覆盖)。所以 tomalak 是正确的,name 将由身份模板处理。 (这就是 tomalak 在他的要点中所说的。+1)
【解决方案2】:

看起来您只是按名称对子元素进行排序。如果是这种情况,试试这个...

XSLT 1.0

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()">
                <xsl:sort select="local-name()"/>                
            </xsl:apply-templates>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

【讨论】:

  • 不不,我没有按名称排序。这是要求。但不是故意的。
  • 原始问题的最小解决方案,所以+1,我猜。
  • @PSR 如果要以预定义的顺序输出节点,则必须按某些属性对它们进行排序,或者显式地逐个(或逐组)调用它们.如果您愿意,您可以列出它们必须出现在其他地方(例如在外部文档中)的顺序,并使用节点在列表中的位置进行排序。但是如果你想强制一个既不是字母也不是数字的顺序,那么这样的显式列表必须存在于某个地方。
猜你喜欢
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 1970-01-01
  • 1970-01-01
  • 2013-08-06
  • 2010-10-14
相关资源
最近更新 更多