【发布时间】: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 的命名空间声明。