我有以下xml,
<Standards xmlns="http://ws.wso2.org/dataservice">
<Standard>
<ProductID>200057</ProductID>
<Prefix>ISO</Prefix>
<SNumber>1001</SNumber>
<Year>1986</Year>
<Designation>ISO 1001:1986</Designation>
<Publisher>ISO</Publisher>
<ProductDescriptions>
<ProductDescription>
<LanguageCode>en</LanguageCode>
<DescriptionID>372980</DescriptionID>
</ProductDescription>
<ProductDescription>
<LanguageCode>fr</LanguageCode>
<DescriptionID>1878599</DescriptionID>
</ProductDescription>
</ProductDescriptions>
<IndustryCodes/>
<ProductAttributes/>
<ProductReconfirmationNotices/>
</Standard>
</Standards>
并希望将其转换为以下格式。
<Standards xmlns="http://ws.wso2.org/dataservice">
<Standard>
<ProductID>200057</ProductID>
<Prefix>ISO</Prefix>
<SNumber>1001</SNumber>
<Year>1986</Year>
<Designation>ISO 1001:1986</Designation>
<Publisher>ISO</Publisher>
<ProductDescriptions>
<LanguageCode>en</LanguageCode>
<DescriptionID>372980</DescriptionID>
</ProductDescriptions>
<ProductDescriptions>
<LanguageCode>fr</LanguageCode>
<DescriptionID>1878599</DescriptionID>
</ProductDescriptions>
<IndustryCodes/>
<ProductAttributes/>
</Standard>
</Standards>
我能够使用以下xslt模板匹配来完成它。它所做的是将所有具有ProductDescription、IndustryCode、ProductAttribute、SaleItem或SaleItemAttribute等的元素作为子元素,并将其替换为源xml中的父元素名称。
<xsl:template
match="*[x:ProductDescription]|*[x:IndustryCode]|*[x:ProductAttribute]|*[x:SaleItem]|*[x:SaleItemAttribute]|*[x:SaleItemfile]|*[x:SaleItemPrice]">
<xsl:apply-templates />
</xsl:template>
<!-- Replace "item" with its parent in source XML -->
<xsl:template
match="x:ProductDescription|x:IndustryCode|x:ProductAttribute|x:SaleItem|x:SaleItemAttribute|x:SaleItemfile|x:SaleItemPrice">
<xsl:element name="{name(..)}">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
但现在我需要添加一个XML处理指令,生成的XML应该是这样的。如果这里有很多这样的元素,比如ProductDescription,我只需要在这些元素第一次出现之前添加PI。此外,如果没有元素(即空元素)(如IndustryCodes),甚至只有一个元素(如Standard),我需要添加相同的PI。
<Standards xmlns="http://ws.wso2.org/dataservice">
<?xml-multiple ?>
<Standard>
<ProductID>200057</ProductID>
<Prefix>ISO</Prefix>
<SNumber>1001</SNumber>
<Year>1986</Year>
<Designation>ISO 1001:1986</Designation>
<Publisher>ISO</Publisher>
<?xml-multiple ?>
<ProductDescriptions>
<LanguageCode>en</LanguageCode>
<DescriptionID>372980</DescriptionID>
</ProductDescriptions>
<ProductDescriptions>
<LanguageCode>fr</LanguageCode>
<DescriptionID>1878599</DescriptionID>
</ProductDescriptions>
<?xml-multiple ?>
<IndustryCodes/>
<?xml-multiple ?>
<ProductAttributes/>
</Standard>
</Standards>
XML处理指令(PI)可以在xslt中添加如下。
<xsl:processing-instruction name="xml-multiple"/>
我如何才能更改上面的模板来完成这件事。感谢您的帮助。
对于替换父元素的现有模板,您可以直接在指令中添加
<xsl:template
match="*[x:ProductDescription]|*[x:IndustryCode]|*[x:ProductAttribute]|*[x:SaleItem]|*[x:SaleItemAttribute]|*[x:SaleItemfile]|*[x:SaleItemPrice]">
<xsl:processing-instruction name="xml-multiple"/>
<xsl:apply-templates />
</xsl:template>
然后,您需要一个单独的模板来处理空元素
<xsl:template
match="x:ProductDescriptions|x:IndustryCodes|x:ProductAttributes|x:SaleItems|x:SaleItemAttributes|x:SaleItemfiles|x:SaleItemPrices">
<xsl:processing-instruction name="xml-multiple"/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
</xsl:copy>
</xsl:template>
请注意,您不需要检查它们是否有子元素。因为当他们有子模板时,另一个模板与他们匹配,所以将使用该模板,因为它具有更高的优先级(因为它具有条件检查)。
您也可以将Standard
元素添加到此列表中。
尝试此XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:x="http://ws.wso2.org/dataservice">
<xsl:output method="xml" indent="yes" />
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="x:Standard|x:ProductDescriptions|x:IndustryCodes|x:ProductAttributes|x:SaleItems|x:SaleItemAttributes|x:SaleItemfiles|x:SaleItemPrices">
<xsl:processing-instruction name="xml-multiple"/>
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="*[x:ProductDescription]|*[x:IndustryCode]|*[x:ProductAttribute]|*[x:SaleItem]|*[x:SaleItemAttribute]|*[x:SaleItemfile]|*[x:SaleItemPrice]" >
<xsl:processing-instruction name="xml-multiple"/>
<xsl:apply-templates />
</xsl:template>
<!-- Replace "item" with its parent in source XML -->
<xsl:template
match="x:ProductDescription|x:IndustryCode|x:ProductAttribute|x:SaleItem|x:SaleItemAttribute|x:SaleItemfile|x:SaleItemPrice">
<xsl:element name="{name(..)}" namespace="http://ws.wso2.org/dataservice">
<xsl:apply-templates />
</xsl:element>
</xsl:template>
</xsl:stylesheet>