【问题标题】:XSLT to add prefix namespaces of all nodes except fewXSLT 添加除少数节点之外的所有节点的前缀命名空间
【发布时间】:2016-01-18 08:22:18
【问题描述】:

我正在尝试编写 XSLT 代码以将前缀命名空间添加到除少数节点之外的所有节点。

示例 XML:

    <BatchPrepareDeliverArchive xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="schema">
<BatchInformation>
    <RqUId>424000000071256187550913330</RqUId>
    <BatchFeedId>CMLTREXT4240</BatchFeedId>
    <BatchCount>7</BatchCount>
</BatchInformation>
<BatchDeliverArchive>
    <Transactions>
        <Transaction>
            <TransactionUUID>90022016-01-140000001</TransactionUUID>
            <CustomerData>
                <GBD_Transactions>
                    <GBD_Transaction>
                        <Common_Data>
                            <Transaction_ID>90022016-01-140000001</Transaction_ID>
                            </Common_Data>
                        <Templates>
                            <Template>
                                <Template_Name>A21_LETTER_FINAL_NOTICE_OF_CANCELLATION_TPA</Template_Name>
                                <Transaction_ID>90022016-01-140000001</Transaction_ID>
                                </Template>
                        </Templates>
                    </GBD_Transaction>
                </GBD_Transactions>
            </CustomerData>
            <DocInfo>
                <Name>OPERATION NAME</Name>
                </DocInfo>
            </Transaction>
            </Transactions>
            </BatchDeliverArchive>
    </BatchPrepareDeliverArchive>

我想为所有节点添加 urn 前缀,除了 GBD_Transactions 及其子元素。

我想出了这个 XSLT:

    <xsl:stylesheet version="1.0"  xmlns:urn="http://www.w3.org/2001/XMLSchema-instance"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:template match="*">
    <xsl:element name="urn:{local-name()}">
    <xsl:apply-templates/>
    </xsl:element>
    </xsl:template>

    <xsl:template match="@*">
    <xsl:element name="urn:{local-name()}">
    <xsl:value-of select="."/>
    </xsl:element>
    </xsl:template>

    </xsl:stylesheet>

所有节点都在此处进行转换,这不是预期的输出。 非常感谢您对此的任何帮助!

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    如果您想忽略GBD_Transactions 元素及其后代,只需添加一个模板以匹配相关节点,并使用标识模板原样复制它们。

    尝试将此模板添加到 XSLT

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

    请注意,匹配特定元素名称的优先级高于匹配 *,因此应始终先使用此模板,然后再使用更通用的模板。

    顺便说一句,与“*”匹配的模板存在问题。你可能把它改成这个......

    <xsl:template match="*">
      <xsl:element name="urn:{local-name()}">
        <xsl:apply-templates select="@*|node()" />
       </xsl:element>
    </xsl:template>
    

    这是因为&lt;xsl:apply-templates /&gt;&lt;xsl:apply-templates select="node()" /&gt; 一样,所以不会选择属性。因此,与@* 匹配的现有模板不会被调用。

    编辑:如果你想阻止 xsi:schemaLocation 属性成为一个元素,也添加这个模板(你需要在 XSLT 中声明 xsi 命名空间)

    <xsl:template match="@xsi:*">
        <xsl:copy />
    </xsl:template>
    

    或者您不希望将任何属性更改为元素?试试这个 XSLT?

    <xsl:stylesheet version="1.0"  xmlns:urn="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>
    
        <xsl:template match="*">
        <xsl:element name="urn:{local-name()}">
        <xsl:apply-templates select="@*|node()" />
        </xsl:element>
        </xsl:template>
    
        <xsl:template match="@*">
            <xsl:copy />
        </xsl:template>
    
        <xsl:template match="GBD_Transactions|GBD_Transactions//*|GBD_Transactions//@*">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()" />
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    【讨论】:

    • 嗨蒂姆,感谢您的回答。但是我看到 xsi:schema 属性被转换为文本节点。另外,我不想为 GBD_Transactions 声明命名空间。有什么办法可以去掉吗?
    • 我可以处理那个命名空间,谢谢。
    【解决方案2】:

    在匹配“*”的模板中,你应该这样区分:

    <xsl:template match="*">
        <xsl:choose>
            <xsl:when test="ancestor-or-self::GBD_Transactions">
                <xsl:copy>
                    <xsl:apply-templates"/>
                </xsl:copy>
            </xsl:when>
            <xsl:otherwise>
                <xsl:element name="urn:{local-name()}">
                    <xsl:apply-templates/>
                </xsl:element>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>
    

    输出将如下所示:

    <urn:BatchPrepareDeliverArchive xmlns:urn="http://www.w3.org/2001/XMLSchema-instance">
        <urn:BatchInformation>
            <urn:RqUId>424000000071256187550913330</urn:RqUId>
            <urn:BatchFeedId>CMLTREXT4240</urn:BatchFeedId>
            <urn:BatchCount>7</urn:BatchCount>
        </urn:BatchInformation>
        <urn:BatchDeliverArchive>
            <urn:Transactions>
                <urn:Transaction>
                    <urn:TransactionUUID>90022016-01-140000001</urn:TransactionUUID>
                    <urn:CustomerData>
                        <GBD_Transactions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                            <GBD_Transaction>
                                <Common_Data>
                                    <Transaction_ID>90022016-01-140000001</Transaction_ID>
                                </Common_Data>
                                <Templates>
                                    <Template>
                                        <Template_Name>A21_LETTER_FINAL_NOTICE_OF_CANCELLATION_TPA</Template_Name>
                                        <Transaction_ID>90022016-01-140000001</Transaction_ID>
                                    </Template>
                                </Templates>
                            </GBD_Transaction>
                        </GBD_Transactions>
                    </urn:CustomerData>
                    <urn:DocInfo>
                        <urn:Name>OPERATION NAME</urn:Name>
                    </urn:DocInfo>
                </urn:Transaction>
            </urn:Transactions>
        </urn:BatchDeliverArchive>
    </urn:BatchPrepareDeliverArchive>
    

    这是你想要的吗?

    【讨论】:

    • 感谢 Kimmy 的回答。输出符合预期,我们不能从 GBD_Transactions 节点中删除命名空间声明吗?
    • 我可以处理那个命名空间,谢谢。