如何选择属性的下一个兄弟

时间:2016-03-30 12:48:53

标签: xml xslt xpath

我想选择属性的下一个兄弟来输出句点。 此模板正在选择所需的属性。

唯一有效的解决方案是我匹配属性的名称并选择我需要的那个。如何使用少量线使其更通用? 我已经尝试过跟随兄弟姐妹'但这只适用于元素。

功能代码;

             ...
                <Period >
                    <xsl:attribute name="Unit">
                        <xsl:choose>
                            <xsl:when test="local-name()='BonusAmount'">
                                <xsl:value-of select="../@BonusFrequency"/>
                            </xsl:when>
                            <xsl:when test="local-name()='CommissionAmount'">
                                <xsl:value-of select="../@CommissionFrequency"/>
                            </xsl:when>
                            <xsl:when test="local-name()='GrossRegularOvertimeAmount'">
                                <xsl:value-of select="../@GrossRegularOvertimeFrequency"/>
                            </xsl:when>
                            <xsl:when test="local-name()='GrossSalaryAmount'">
                                <xsl:value-of select="../@GrossSalaryFrequency"/>
                            </xsl:when>
                            <xsl:when test="local-name()='CarAllowanceAmount'">
                                <xsl:value-of select="../@CarAllowanceFrequency"/>
                            </xsl:when>
                            <xsl:when test="local-name()='WorkAllowanceAmount'">
                                <xsl:value-of select="../@WorkAllowanceFrequency"/>
                            </xsl:when>
                            <xsl:when test="local-name()='WorkersCompensationAmount'">
                                <xsl:value-of select="../@WorkersCompensationFrequency"/>
                            </xsl:when>

                        </xsl:choose>
                    </xsl:attribute>
                </Period>
           ...

XML示例:

 <Employment>
      <PAYG Basis="Temporary" Industry="Oil and Gas Extraction" IndustryCode="0700" Occupation="General Waiter" OccupationCode="6323-11" OnProbation="Yes" ProbationDateEnds="2019-03-27" StartDate="2014-05-05" Status="Secondary" UniqueID="c8492d8c-34fc-419b-93f4-f1f3" x_Employer="c46c9077-31ef-4daa-b8cc-c9e3">
        <Income BonusAmount="89898985" BonusFrequency="Monthly" CommissionAmount="4488" CommissionFrequency="Yearly" GrossRegularOvertimeAmount="365" GrossRegularOvertimeFrequency="Fortnightly" GrossSalaryAmount="4798" GrossSalaryFrequency="Weekly"  WorkAllowanceAmount="10101010" WorkAllowanceFrequency="Monthly"/>
      </PAYG>
    </Employment>

输出:

<ValueItem Value="89898985">
        <Identifier UniqueID="c8492d8c-34fc-419b-93f4-f1f3-Income-PAYG-BonusAmount"/>
        <PercentOwned Percent="100">
           <RelatedEntityRef RelatedID="baaef85e-3793-4fe8-8c62-8cc766fa490b"/>
        </PercentOwned>
        <Income Type="Bonus">
           <Period Unit="Monthly"/>
           <RelatedEntityRef RelatedID="c46c9077-31ef-4daa-b8cc-c9e3"/>
        </Income>
     </ValueItem>
     <ValueItem Value="4488">
        <Identifier UniqueID="c8492d8c-34fc-419b-93f4-f1f3-Income-PAYG-CommissionAmount"/>
        <PercentOwned Percent="100">
           <RelatedEntityRef RelatedID="baaef85e-3793-4fe8-8c62-8cc766fa490b"/>
        </PercentOwned>
        <Income Type="Commission">
           <Period Unit="Yearly"/>
           <RelatedEntityRef RelatedID="c46c9077-31ef-4daa-b8cc-c9e3"/>
        </Income>
     </ValueItem>
     <ValueItem Value="365">
        <Identifier UniqueID="c8492d8c-34fc-419b-93f4-f1f3-Income-PAYG-GrossRegularOvertimeAmount"/>
        <PercentOwned Percent="100">
           <RelatedEntityRef RelatedID="baaef85e-3793-4fe8-8c62-8cc766fa490b"/>
        </PercentOwned>
        <Income Type="GrossRegularOvertime">
           <Period Unit="Fortnightly"/>
           <RelatedEntityRef RelatedID="c46c9077-31ef-4daa-b8cc-c9e3"/>
        </Income>
     </ValueItem>
     <ValueItem Value="4798">
        <Identifier UniqueID="c8492d8c-34fc-419b-93f4-f1f3-Income-PAYG-GrossSalaryAmount"/>
        <PercentOwned Percent="100">
           <RelatedEntityRef RelatedID="baaef85e-3793-4fe8-8c62-8cc766fa490b"/>
        </PercentOwned>
        <Income Type="GrossSalary">
           <Period Unit="Weekly"/>
           <RelatedEntityRef RelatedID="c46c9077-31ef-4daa-b8cc-c9e3"/>
        </Income>
     </ValueItem>

2 个答案:

答案 0 :(得分:0)

对于XSLT 2.0及更高版本,您可以使用fn:replace() XPath function,如下所示:

<Period Unit="{../@*[name()= replace(name(current()),'Amount','Frequency')]}"/>

XSLT 1.0没有此功能。其中一种解决方法如下(将任意输入字符串映射到任意输出字符串,这比replace()可以做的更灵活一些):

<xsl:transform 
    version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="http://tempuri.org/"
    exclude-result-prefixes="my"
>
    <xsl:output method="xml" encoding="UTF-8" indent="yes" />

    <my:config>
        <map value="BonusAmount">BonusFrequency</map>
        <map value="CommissionAmount">CommissionFrequency</map>
        <!-- ... -->
    </my:config>
    <xsl:variable name="config" select="document('')/*/my:config" />

    <xsl:template match="@*" mode="create-period">
        <xsl:variable name="mapping" select="$config/map[@value = name(current())]" />
        <xsl:if test="$mapping">
            <Period Unit="{../@*[name() = $mapping]}" />
        </xsl:if>
    </xsl:template>

</xsl:transform>

注意:

  • document('')可用于访问当前的XSLT文档
  • 自定义命名空间允许将数据嵌入样式表
  • exclude-result-prefixes可防止名称空间泄漏到输出文档中
  • 可以使用属性值模板(花括号)代替<xsl:attribute>(只要属性名称是固定的,就像你的情况一样)。
  • 请注意模板模式,以区别于可能与@*匹配的其他模板。需要在应用模板时设置。

另一种可能性包括string-replace template或使用EXSLT replace extension function - 许多XSLT 1.0处理器都支持EXSLT。

答案 1 :(得分:0)

我不确定我是否完全理解这一点 如果您需要查找以 Amoun 结尾的每个属性,以频率结尾的属性  你可以试试这样的黑客:

    <xsl:template match="PAYG">
        <test>
            <xsl:apply-templates select="Income/@*" />
        </test>
    </xsl:template>

    <xsl:template match="Income/@*">
        <xsl:variable name="a" select="local-name()" />
        <xsl:if test="'Amount' =  substring( $a, string-length($a) - string-length('Amount') + 1 )">
            <xsl:variable name="f"  select="concat( substring-before( $a, 'Amount' ), 'Frequency' )"/>
            <Period >
                <xsl:attribute name="Unit">
                    <xsl:value-of select="../@*[local-name() = $f]"/>
                </xsl:attribute>
                    <xsl:value-of select="local-name()"/>
            </Period>
        </xsl:if>
    </xsl:template>

将输出:

<test>
 <Period Unit="Monthly">BonusAmount</Period>
 <Period Unit="Yearly">CommissionAmount</Period>
 <Period Unit="Fortnightly">GrossRegularOvertimeAmount</Period>
 <Period Unit="Weekly">GrossSalaryAmount</Period>
 <Period Unit="Monthly">WorkAllowanceAmount</Period>
</test>