如果只有一个或零个(空)元素,则在元素之前添加XML处理指令



我有以下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>

相关内容

  • 没有找到相关文章

最新更新