使用 XSLT 根据特定键值合并 XML 个节点
Merge XML nodes based on Certain Key Value using XSLT
根据 ReferenceNumber 值合并 XML 个节点
如何使用基于键值的 XSLT 将 xml 请求合并到下面给出的输出。
基本上,ReferenceNumber 的 xml 响应必须与相应的 ProductCode 和 SecondaryDivision 合并。
以下是请求和预期响应。
我尝试使用以下 XSLT,但没有得到预期的结果。
下面是 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="refNo" match="Envelope/Body/DocumentMetadataResponse" use="ReferenceNumber" />
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Envelope/Body/DocumentMetadataResponse/DocumentMetadata" />
<xsl:template match="Envelope/Body/DocumentMetadataResponse/DocumentMetadata[generate-id()=generate-id(key('refNo', DocumentMetadata/ReferenceNumber))]">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="DocumentMetadata">
<xsl:copy>
<xsl:apply-templates select="@*|ReferenceNumber" />
<divisionses>
<xsl:apply-templates select="key('refNo', ReferenceNumber)/DocumentMetadata" mode="divisions" />
</divisionses>
</xsl:copy>
</xsl:template>
<xsl:template match="DocumentMetadata" mode="divisions">
<Divisions>
<xsl:apply-templates select="*[not(self::ReferenceNumber)]" />
</Divisions>
</xsl:template>
</xsl:stylesheet>
输入XML
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
<PageNumber>1</PageNumber>
<PageSize>1000</PageSize>
<TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<SecondaryDivision>AT</SecondaryDivision>
<ProductCode>Product-AT-01</ProductCode>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<SecondaryDivision>AT</SecondaryDivision>
<ProductCode>Product-AT-02</ProductCode>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<SecondaryDivision>BE</SecondaryDivision>
<ProductCode>Product-BE-01</ProductCode>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-02</ReferenceNumber>
<SecondaryDivision>BS</SecondaryDivision>
<ProductCode>Product-BS-01</ProductCode>
</DocumentMetadata>
</ns2:DocumentMetadataResponse>
</soap:Body>
</soap:Envelope>
预期输出XML
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
<PageNumber>1</PageNumber>
<PageSize>1000</PageSize>
<TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>AT</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-AT-01</ProductCode>
</Product>
<Product>
<ProductCode>Product-AT-02</ProductCode>
</Product>
</Products>
</Division>
<Division>
<SecondaryDivision>BE</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BE-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-02</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>BS</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BS-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
</ns2:DocumentMetadataResponse>
</soap:Body>
</soap:Envelope>
您可以使用此 XSLT-2.0 模板来完成这项工作。 xsl:for-each-group
执行两级分组:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="http://www.example.com/mService">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:DocumentMetadataResponse ">
<xsl:copy>
<xsl:apply-templates select="@*|* except DocumentMetadata" />
<xsl:for-each-group select="DocumentMetadata" group-by="ReferenceNumber">
<DocumentMetadata>
<ReferenceNumber><xsl:value-of select="current-grouping-key()" /></ReferenceNumber>
<Divisions>
<xsl:for-each-group select="current-group()" group-by="SecondaryDivision">
<Division>
<SecondaryDivision><xsl:value-of select="current-grouping-key()" /></SecondaryDivision>
<Products>
<xsl:for-each select="current-group()">
<Product>
<ProductCode><xsl:value-of select="ProductCode" /></ProductCode>
</Product>
</xsl:for-each>
</Products>
</Division>
</xsl:for-each-group>
</Divisions>
</DocumentMetadata>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出为:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
<PageNumber>1</PageNumber>
<PageSize>1000</PageSize>
<TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>AT</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-AT-01</ProductCode>
</Product>
<Product>
<ProductCode>Product-AT-02</ProductCode>
</Product>
</Products>
</Division>
<Division>
<SecondaryDivision>BE</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BE-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-02</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>BS</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BS-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
</ns2:DocumentMetadataResponse>
</soap:Body>
</soap:Envelope>
根据 ReferenceNumber 值合并 XML 个节点
如何使用基于键值的 XSLT 将 xml 请求合并到下面给出的输出。 基本上,ReferenceNumber 的 xml 响应必须与相应的 ProductCode 和 SecondaryDivision 合并。 以下是请求和预期响应。
我尝试使用以下 XSLT,但没有得到预期的结果。
下面是 XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="refNo" match="Envelope/Body/DocumentMetadataResponse" use="ReferenceNumber" />
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="Envelope/Body/DocumentMetadataResponse/DocumentMetadata" />
<xsl:template match="Envelope/Body/DocumentMetadataResponse/DocumentMetadata[generate-id()=generate-id(key('refNo', DocumentMetadata/ReferenceNumber))]">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="DocumentMetadata">
<xsl:copy>
<xsl:apply-templates select="@*|ReferenceNumber" />
<divisionses>
<xsl:apply-templates select="key('refNo', ReferenceNumber)/DocumentMetadata" mode="divisions" />
</divisionses>
</xsl:copy>
</xsl:template>
<xsl:template match="DocumentMetadata" mode="divisions">
<Divisions>
<xsl:apply-templates select="*[not(self::ReferenceNumber)]" />
</Divisions>
</xsl:template>
</xsl:stylesheet>
输入XML
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
<PageNumber>1</PageNumber>
<PageSize>1000</PageSize>
<TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<SecondaryDivision>AT</SecondaryDivision>
<ProductCode>Product-AT-01</ProductCode>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<SecondaryDivision>AT</SecondaryDivision>
<ProductCode>Product-AT-02</ProductCode>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<SecondaryDivision>BE</SecondaryDivision>
<ProductCode>Product-BE-01</ProductCode>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-02</ReferenceNumber>
<SecondaryDivision>BS</SecondaryDivision>
<ProductCode>Product-BS-01</ProductCode>
</DocumentMetadata>
</ns2:DocumentMetadataResponse>
</soap:Body>
</soap:Envelope>
预期输出XML
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
<PageNumber>1</PageNumber>
<PageSize>1000</PageSize>
<TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>AT</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-AT-01</ProductCode>
</Product>
<Product>
<ProductCode>Product-AT-02</ProductCode>
</Product>
</Products>
</Division>
<Division>
<SecondaryDivision>BE</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BE-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-02</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>BS</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BS-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
</ns2:DocumentMetadataResponse>
</soap:Body>
</soap:Envelope>
您可以使用此 XSLT-2.0 模板来完成这项工作。 xsl:for-each-group
执行两级分组:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns2="http://www.example.com/mService">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="ns2:DocumentMetadataResponse ">
<xsl:copy>
<xsl:apply-templates select="@*|* except DocumentMetadata" />
<xsl:for-each-group select="DocumentMetadata" group-by="ReferenceNumber">
<DocumentMetadata>
<ReferenceNumber><xsl:value-of select="current-grouping-key()" /></ReferenceNumber>
<Divisions>
<xsl:for-each-group select="current-group()" group-by="SecondaryDivision">
<Division>
<SecondaryDivision><xsl:value-of select="current-grouping-key()" /></SecondaryDivision>
<Products>
<xsl:for-each select="current-group()">
<Product>
<ProductCode><xsl:value-of select="ProductCode" /></ProductCode>
</Product>
</xsl:for-each>
</Products>
</Division>
</xsl:for-each-group>
</Divisions>
</DocumentMetadata>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
输出为:
<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ns2:DocumentMetadataResponse xmlns:ns2="http://www.example.com/mService">
<PageNumber>1</PageNumber>
<PageSize>1000</PageSize>
<TotalDocumentsAvailable>4919</TotalDocumentsAvailable>
<DocumentMetadata>
<ReferenceNumber>Ref-01</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>AT</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-AT-01</ProductCode>
</Product>
<Product>
<ProductCode>Product-AT-02</ProductCode>
</Product>
</Products>
</Division>
<Division>
<SecondaryDivision>BE</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BE-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
<DocumentMetadata>
<ReferenceNumber>Ref-02</ReferenceNumber>
<Divisions>
<Division>
<SecondaryDivision>BS</SecondaryDivision>
<Products>
<Product>
<ProductCode>Product-BS-01</ProductCode>
</Product>
</Products>
</Division>
</Divisions>
</DocumentMetadata>
</ns2:DocumentMetadataResponse>
</soap:Body>
</soap:Envelope>