首页 > 解决方案 > 如何使用具有依赖关系的 xslt 排除 xml 对象

问题描述

我有以下输入xml


    <?xml version="1.0" encoding="UTF-8"?>
     <root> 
        <technicalAssets>
            <composedId>
                <id>A1</id> 
            </composedId> 
            <technicalName>TestA1</technicalName> 
            <prerequisites>
                <technicalAssetPrerequisites> 
                    <technicalAssetIds>
                        <composedId>
                            <id>B1</id> 
                        </composedId>
                    </technicalAssetIds>
                </technicalAssetPrerequisites> 
            </prerequisites>
        </technicalAssets>

        <technicalAssets>
            <composedId>
                <id>A2</id> 
            </composedId> 
            <technicalName>TestA2</technicalName> 
        </technicalAssets>

        <technicalAssets>
            <composedId>
                <id>B1</id> 
            </composedId> 
            <technicalName>TestB1</technicalName> 
        </technicalAssets>  

        <products> 
            <entitlementRules>       
                <technicalAssetId>
                    <composedId>
                        <id>A1</id> 
                    </composedId>
                </technicalAssetId>
            </entitlementRules> 

        </products> 

    </root>

我想应用一个 XSLT 转换,它只列出产品technicalAssets中引用的或产品引用的那些。

我怎样才能做到这一点?预期输出:

<?xml version="1.0" encoding="UTF-8"?>
<root> 
    <technicalAssets>
        <composedId>
            <id>A1</id> 
        </composedId> 
        <technicalName>TestA1</technicalName> 
        <prerequisites>
            <technicalAssetPrerequisites> 
                <technicalAssetIds>
                    <composedId>
                        <id>B1</id> 
                    </composedId>
                </technicalAssetIds>
            </technicalAssetPrerequisites> 
        </prerequisites>
    </technicalAssets>

    <technicalAssets>
        <composedId>
            <id>B1</id> 
        </composedId> 
        <technicalName>TestB1</technicalName> 
    </technicalAssets>  

    <products> 
        <entitlementRules>       
            <technicalAssetId>
                <composedId>
                    <id>A1</id> 
                </composedId>
            </technicalAssetId>
        </entitlementRules> 

    </products> 

</root>

我目前正在使用以下 xslt,但它复制了出现 TechnicalAssetId 的产品节点内的节点 TechnicalAssets。那不是我需要的。

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

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

<xsl:template match="technicalAssets"/>

    <xsl:template match="technicalAssetId">
        <xsl:copy>
            <xsl:apply-templates/> 
            <xsl:for-each select="/root/technicalAssets[composedId/id/text() = current()/composedId/id/text()]">
                <xsl:copy-of select="."/>
            </xsl:for-each> 
        </xsl:copy>

    </xsl:template>

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

</xsl:stylesheet>

标签: xmlxslt

解决方案


您可以使用 anxsl:key来选择所有composedId/id不是technicalAssets.

然后,您可以key()在模板中使用匹配的谓词technicalAssets来检查是否没有匹配的键composedId/id

因此,与其尝试复制您想要保留的内容,不如删除您不想保留的内容。

例子...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="ids" match="*[not(self::technicalAssets)]/composedId/id" use="."/>

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

  <xsl:template match="technicalAssets[not(key('ids',composedId/id))]"/>

</xsl:stylesheet>

小提琴:http: //xsltfiddle.liberty-development.net/6rewNya


推荐阅读