【问题标题】:Merge multiple fields into one using xslt使用 xslt 将多个字段合并为一个
【发布时间】:2018-01-07 00:48:20
【问题描述】:

我有一个关于将多个节点合并为一个节点的问题。但我不知道该怎么做。

我有以下 XML 文件:

   <soap:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
               xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
               xmlns:s1="http://microsoft.com/wsdl/types/"
               xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/">
    <soap:Body>
        <RetrieveTicketUpdatesResponse>
            <RetrieveTicketUpdatesResult>
                <TicketUpdates>
                    <TicketUpdate>
                        <FreeFields>
                            <FreeField>
                                <FreeFieldID>9876</FreeFieldID>
                                <Value>Yes</Value>
                            </FreeField>
                        </FreeFields>
                        <FreeFields>
                            <FreeField>
                                <FreeFieldID>8765</FreeFieldID>
                                <Value>Fiber</Value>
                            </FreeField>
                        </FreeFields>
                        <Id>1234</ticketId>
                        <Status>New</status>
                    </TicketUpdate>
                    <TicketUpdate>
                        <TicketUpdate>
                        <FreeFields>
                            <FreeField>
                                <FreeFieldID>6823</FreeFieldID>
                                <Value>No</Value>
                            </FreeField>
                        </FreeFields>
                        <FreeFields>
                            <FreeField>
                                <FreeFieldID>3453</FreeFieldID>
                                <Value>Fiber</Value>
                            </FreeField>
                        </FreeFields>
                        <Id>2343</ticketId>
                        <Status>Update</status>
                    </TicketUpdate>
                </TicketUpdates>
            </RetrieveTicketUpdatesResult>
        </RetrieveTicketUpdatesResponse>
    </soap:Body>
</soap:Envelope>

我想将 FreeFields 节点合并为 1 个节点,如下所示并创建以下输出:

<soap:Envelope xmlns:http="http://schemas.xmlsoap.org/wsdl/http/"
               xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/"
               xmlns:s1="http://microsoft.com/wsdl/types/"
               xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/">
    <soap:Body>
        <RetrieveTicketUpdatesResponse>
            <RetrieveTicketUpdatesResult>
                <TicketUpdates>
                    <TicketUpdate>
                        <FreeFields>
                            <FreeField>
                                <FreeFieldID>9876</FreeFieldID>
                                <Value>Yes</Value>
                            </FreeField>
                            <FreeField>
                                <FreeFieldID>8765</FreeFieldID>
                                <Value>Fiber</Value>
                            </FreeField>
                            <FreeField>
                                <FreeFieldID>7654</FreeFieldID>
                                <Value>https://www.stackoverflow.com</Value>
                            </FreeField>
                        </FreeFields>
                        <Id>1234</ticketId>
                        <Status>New</status>
                    </TicketUpdate>
                    <TicketUpdate>
                        <TicketUpdate>
                        <FreeFields>
                            <FreeField>
                                <FreeFieldID>6823</FreeFieldID>
                                <Value>No</Value>
                            </FreeField>
                            <FreeField>
                                <FreeFieldID>3453</FreeFieldID>
                                <Value>Fiber</Value>
                            </FreeField>
                            <FreeField>
                                <FreeFieldID>8563</FreeFieldID>
                                <Value>https://www.stackexchange.com</Value>
                            </FreeField>
                        </FreeFields>
                        <Id>2343</ticketId>
                        <Status>Update</status>
                    </TicketUpdate>
                </TicketUpdates>
            </RetrieveTicketUpdatesResult>
        </RetrieveTicketUpdatesResponse>
    </soap:Body>
</soap:Envelope>

我尝试使用 xsl:for-each。并将其复制到新列表中,但我不知道如何完成此操作。 有人可以帮我举个例子吗? 我尝试在谷歌上搜索解决方案,但无法找到解决方案。

更新 1 这是我正在使用的 XSLT

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:s1="http://microsoft.com/wsdl/types/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tm="http://microsoft.com/wsdl/mime/textMatching/" version="1.0">

  <xsl:output encoding="utf-8" indent="yes" method="xml" omit-xml-declaration="yes" />

  <!-- Stylesheet to inject namespaces into a document in specific places -->
  <xsl:template match="/">
    <soap:Envelope>
      <soap:Body>
        <RetrieveTicketUpdatesResponse>

          <xsl:choose>
            <!-- Handle 'Root' wrapper added by JSON to XML policy -->
            <xsl:when test="normalize-space(/Root)">
              <RetrieveTicketUpdatesResult>
                <xsl:apply-templates select="node()|@*" />
              </RetrieveTicketUpdatesResult>
            </xsl:when>

            <!-- If the root element is not what was in the schema, add it -->
            <xsl:when test="not(normalize-space(/RetrieveTicketUpdates))">
              <RetrieveTicketUpdatesResult>
                <xsl:apply-templates select="node()|@*" />
              </RetrieveTicketUpdatesResult>
            </xsl:when>
            <!-- everything checks out,  just copy the xml-->
            <xsl:otherwise>
              <xsl:apply-templates select="node()|@*" />
            </xsl:otherwise>
          </xsl:choose>
        </RetrieveTicketUpdatesResponse>
      </soap:Body>
    </soap:Envelope>
  </xsl:template>

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

  <xsl:template match="/FreeFields/*/FreeField" name="copy-freefields">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="*" />
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="/Root/*" name="copy-root">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="namespace::*" />
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="*[not(local-name()='Root') and not(local-name()='Array')]" name="copy-all">
    <xsl:element name="{local-name()}">
      <xsl:copy-of select="namespace::*" />
      <xsl:apply-templates select="node()|@*" />
    </xsl:element>
  </xsl:template>

  <!-- template to copy the rest of the nodes -->
  <xsl:template match="comment() | processing-instruction()">
    <xsl:copy />
  </xsl:template>
</xsl:stylesheet>

【问题讨论】:

  • 请发布您的尝试以便我们修复它,而不必从头开始为您编写代码。还要说明是使用 XSLT 1.0 还是 2.0。
  • 另请注意,您向我们展示的输入和输出都缺少将 soap 前缀绑定到命名空间 URI 的命名空间声明。

标签: xml xslt


【解决方案1】:

试试下面的脚本:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:soap="http://schemas.xmlsoap.org/soap">
  <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
  <xsl:strip-space elements="*"/>

  <xsl:template match="TicketUpdate">
    <xsl:copy>
      <FreeFields>
        <xsl:copy-of select="FreeFields/FreeField"/>
      </FreeFields>
      <xsl:apply-templates select="*[name() != 'FreeFields']"/>
    </xsl:copy>
  </xsl:template>

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

您还必须更正源 XML 中的一些错误。

【讨论】:

  • Tnx! :) 我的源 XML 更大,并且去掉了很多额外的节点。我想我没有正确编辑它。你的解决方案就像一个魅力
猜你喜欢
  • 2021-09-22
  • 1970-01-01
  • 2018-07-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多