按特定顺序添加子元素

时间:2017-02-07 15:53:35

标签: xslt xpath

我正在通过XSLT进行xml到xml的转换。我有以下内容:

stylesheet.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns="http://www.test.org"
xmlns:xs="http://www.w3.org/2001/XMLSchema"  version="2.0"> <!-- xs namespace allows typed functions and parameters -->
<xsl:output method="xml" indent="yes" version="1.0" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*" /> 

<xsl:param name="other-id" select="Request/Order/OtherId" />

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

<xsl:template match="@*|text()|comment()|processing-instruction()">
    <xsl:copy />
</xsl:template>

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

<xsl:template match="Details">
    <xsl:element name="{local-name()}">
        <xsl:element name="Signon>
            <xsl:element name="SignonDt>2017-01-01</xsl:element>
            <xsl:element name="MessageQuantity">3</xsl:element>
        <xsl:element>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="NotificationRq">
    <xsl:element name="{local-name()}">
        <xsl:element name="RqUID">Test</xsl:element>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template match="Policy/SDDCd" />

<xsl:template match="Policy">
    <xsl:element name="{local-name()}">
        <xsl:element name="RFDCd">
            <xsl:call-template name="getRFDCd" />
        </xsl:element>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<xsl:template name="getRFDCd">
    <xsl:choose>
        <xsl:when test="contains($other-id, 'RFD 2')">
            <xsl:text>AUB</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>CL</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="Contact/Addr" >
    <xsl:element name="{local-name()}">
        <xsl:element name="AddrTypeCd">StreetAddress</xsl:element>
        <xsl:apply-templates />
    </xsl:element>
</xsl:template>

<!-- other templates structured similar to these -->

input.xml中

<Request>
    <Details>
        <NotificationRq>
            <RqDate>2017-01-01</RqDate>
            <RqDetails>
            <!-- other children -->
            <RqDetails>
        </NotificationRq>
        <Policy>
            <PolNumber>1234567890</PolNumber>
            <SDDCd>T35</SDDCd>
        </Policy>
        <Contact>
            <Addr>
                <AddrLn1>Test address line 1</AddrLn1>
                <AddrLn2>Test address line 2</AddrLn2>
                <PostCode>AX12D3</PostCode>
            </Addr>
        </Contact>
        <!-- other children -->
    </Details>
</Request>

的Output.xml

<Details xmlns="http://test.org">
    <Signon>
        <SignonDt>2017-01-01</Signon>
        <MessageQuantity>3</MessageQuantity>
    </Signon>
    <NotificationRq>
        <RqUId>Test</RqUID>
        <RqDate>2017-01-01</RqDate>
        <RqDetails>
            <!-- other children -->
        <RqDetails>
    </NotificationRq>
    <Policy>
        <RFDCd>CL</RFDCd>
        <PolNumber>1234567890</PolNumber>
    </Policy>
    <Contact>
        <Addr>
            <AddrTypeCd>StreetAddress</AddrTypeCd>
            <AddrLn1>Test address line 1</AddrLn1>
            <AddrLn2>Test address line 2</AddrLn2>
            <PostCode>AX12D3</PostCode>
        </Addr>
    </Contact>
    <!-- other children -->
</Details>

注意:由于之前的问题,我使用<xsl:element name="{local-name()}">;我正在将没有命名空间的源xml复制到新输出中,并且此解决方案以及标识转换旁边的额外模板修复了添加到所有元素的命名空间属性的问题

问题是,这个xml是在发生模式验证的下游发送的,因此,新创建的子元素的位置很重要。如上面的代码段所示,新的子元素被添加为父元素的第一个子元素。对于某些情况,这很好,这是它们应该的位置,但对于大约一半的创建元素,它们必须出现在最后(奇数一个或两个需要在指定位置插入)。仍然使用input.xml作为示例,以下是所需输出的外观:

期望-的Output.xml

<Details xmlns="http://test.org">
    <NotificationRq>
        <RqDate>2017-01-01</RqDate>
        <RqDetails>
            <!-- other children -->
        <RqDetails>
        <RqUId>Test</RqUID>
    </NotificationRq>
    <Signon>
        <SignonDt>2017-01-01</Signon>
        <MessageQuantity>3</MessageQuantity>
    </Signon>
    <Policy>
        <PolNumber>1234567890</PolNumber>
        <RFDCd>CL</RFDCd>
    </Policy>
    <Contact>
        <Addr>
            <AddrLn1>Test address line 1</AddrLn1>
            <AddrLn2>Test address line 2</AddrLn2>
            <AddrTypeCd>StreetAddress</AddrTypeCd>
            <PostCode>AX12D3</PostCode>
        </Addr>
    </Contact>
    <!-- other children -->
</Details>

有没有办法指定新子元素的现有子顺序中应该出现的位置?是我的一个模板导致插入顺序始终位于第一个位置吗?

附加信息:我已经看到了关于特定订单插入的一些问题,但它们通常似乎是针对一系列元素或一系列重复元素,例如如何在一系列作者元素中插入另一个作者元素,并且解决方案倾向于使用位置函数来确定是否已经循环到正确的索引,然后插入。我正在使用的xml由可能包含值的唯一元素组成,或者可能包含多个子元素(其中一些包含子元素等)。 xml中没有重复元素,所以我认为我不能使用上面描述的解决方案(除非有人知道如何为元素的非重复子元素做这样的事情)。另外,我使用的是Saxon HE版本9.7.0-8

1 个答案:

答案 0 :(得分:1)

为什么你不能做到:

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

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

<xsl:template match="comment()|processing-instruction()">
    <xsl:copy/>
</xsl:template>

<xsl:template match="/*">
    <xsl:apply-templates/>
</xsl:template>

<xsl:template match="NotificationRq">
    <NotificationRq>
        <xsl:apply-templates/>
        <RqUId>Test</RqUId>
     </NotificationRq>
</xsl:template>

</xsl:stylesheet>
相关问题