根据值

时间:2016-04-05 09:25:27

标签: xml xslt xslt-1.0 xslt-2.0

我正在尝试创建具有基于输入xml的重复元素的xml结构。在输入重复元素MDMTagTagProperties中只有2个字段KeyValue。基于Key字段,我们需要在输出xml中创建一个元素,并将Value字段的内容设置为该元素。 Key字段的最后3个数字字符对于一个子集是相同的。下面是输入XML,我正在尝试的xslt和Desired Output。

输入:

<?xml version="1.0" encoding="UTF-8"?>
<ns1:Properties xmlns:ns1="http://www.test.org/cmm/xsd/mdmtag_01">
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.MeteringDirection.2.8.1</ns1:Key>
        <ns1:Value>TLV</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.MultiplicationFactor.1.8.2</ns1:Key>
        <ns1:Value>2.0</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.MeasureUnit.2.8.1</ns1:Key>
        <ns1:Value>KWH</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.RegisterType.1.8.2</ns1:Key>
        <ns1:Value>N</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.MeteringDirection.1.8.2</ns1:Key>
        <ns1:Value>LVR</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.MultiplicationFactor.2.8.1</ns1:Key>
        <ns1:Value>5.0</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.NrOfDigits.1.8.2</ns1:Key>
        <ns1:Value>5</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.MeasureUnit.1.8.2</ns1:Key>
        <ns1:Value>KWH</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.RegisterType.2.8.1</ns1:Key>
        <ns1:Value>P</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.NrOfDigits.2.8.1</ns1:Key>
        <ns1:Value>4</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.Id.2.8.1</ns1:Key>
        <ns1:Value>2.8.1</ns1:Value>
    </ns1:MDMTagTagProperties>
    <ns1:MDMTagTagProperties>
        <ns1:Key>register.Id.1.8.2</ns1:Key>
        <ns1:Value>1.8.2</ns1:Value>
    </ns1:MDMTagTagProperties>
</ns1:Properties>

XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.test.org/cmm/xsd/mdmtag_01" xmlns:ns5="http://www.test.org/cmm/xsd/outputmdmtag_01" exclude-result-prefixes="ns1" version="1.0">
    <xsl:output method="xml" indent="yes" />

   <xsl:template match="/ns1:Properties">
    <ns5:Output>
        <xsl:for-each select="ns1:MDMTagTagProperties[contains(ns1:Key,'register.Id')]">
            <ns5:Register>
                <ns5:RegisterId>
                     <xsl:value-of select="current()/ns1:Value[contains(ns1:Key,'register.Id')]" />
                </ns5:RegisterId>

                <ns5:RegisterType>
                 <xsl:value-of select="current()/ns1:Value[contains(ns1:Key,'register.RegisterType')]" />
                </ns5:RegisterType>
                <ns5:RegisterMultiplicationFactor>
                   <xsl:value-of select="current()/ns1:Value[contains(ns1:Key,'register.RegisterMultiplicationFactor')]" />
                </ns5:RegisterMultiplicationFactor>
                  <ns5:RegisterMeteringDirection>
                  <xsl:value-of select="current()/ns1:Value[contains(ns1:Key,'register.RegisterMeteringDirection')]" />
                </ns5:RegisterMeteringDirection>
                <ns5:RegisterMeasureUnit>
                    <xsl:value-of select="current()/ns1:Value[contains(ns1:Key,'register.RegisterMeasureUnit')]" />
                </ns5:RegisterMeasureUnit>
                 <ns5:RegisterNrOfDigits>
                   <xsl:value-of select="current()/ns1:Value[contains(ns1:Key,'register.RegisterNrOfDigits')]" />
                </ns5:RegisterNrOfDigits>
            </ns5:Register>
        </xsl:for-each>
    </ns5:Output>
</xsl:template>
</xsl:stylesheet>

CurrentOutput:

<?xml version="1.0" encoding="UTF-8"?>
<ns5:Output xmlns:ns5="http://www.test.org/cmm/xsd/outputmdmtag_01">
    <ns5:Register>
        <ns5:RegisterId />
        <ns5:RegisterType />
        <ns5:RegisterMultiplicationFactor />
        <ns5:RegisterMeteringDirection />
        <ns5:RegisterMeasureUnit />
        <ns5:RegisterNrOfDigits />
    </ns5:Register>
    <ns5:Register>
        <ns5:RegisterId />
        <ns5:RegisterType />
        <ns5:RegisterMultiplicationFactor />
        <ns5:RegisterMeteringDirection />
        <ns5:RegisterMeasureUnit />
        <ns5:RegisterNrOfDigits />
    </ns5:Register>
</ns5:Output>

ExpectedOutput:

<?xml version="1.0" encoding="UTF-8"?>
<ns5:Output xmlns:ns5="http://www.test.org/cmm/xsd/outputmdmtag_01">
    <ns5:Register>
        <ns5:RegisterId>1.8.2</ns5:RegisterId>
        <ns5:RegisterType>N</ns5:RegisterType>
        <ns5:RegisterMultiplicationFactor>2.0</ns5:RegisterMultiplicationFactor>
        <ns5:RegisterMeteringDirection>LVR</ns5:RegisterMeteringDirection>
        <ns5:RegisterMeasureUnit>KHW</ns5:RegisterMeasureUnit>
        <ns5:RegisterNrOfDigits>5</ns5:RegisterNrOfDigits>
    </ns5:Register>
    <ns5:Register>
        <ns5:RegisterId>2.8.1</ns5:RegisterId>
        <ns5:RegisterType>P</ns5:RegisterType>
        <ns5:RegisterMultiplicationFactor>5.0</ns5:RegisterMultiplicationFactor>
        <ns5:RegisterMeteringDirection>TLV</ns5:RegisterMeteringDirection>
        <ns5:RegisterMeasureUnit>KWH</ns5:RegisterMeasureUnit>
        <ns5:RegisterNrOfDigits>4</ns5:RegisterNrOfDigits>
    </ns5:Register>
</ns5:Output>

任何帮助都会很有帮助。

2 个答案:

答案 0 :(得分:1)

考虑使用密钥从输入XML

中查找其他值
<xsl:key name="tags" match="ns1:MDMTagTagProperties" use="ns1:Key" />
例如,他们要查找MultiplicationFactor你会这样做:

<xsl:value-of select="key('tags', concat('register.MultiplicationFactor.', ns1:Value))/ns1:Value" />

试试这个XSLT

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.test.org/cmm/xsd/mdmtag_01" xmlns:ns5="http://www.test.org/cmm/xsd/outputmdmtag_01" exclude-result-prefixes="ns1" version="1.0">
    <xsl:output method="xml" indent="yes" />

   <xsl:key name="tags" match="ns1:MDMTagTagProperties" use="ns1:Key" />

   <xsl:template match="/ns1:Properties">
    <ns5:Output>
        <xsl:for-each select="ns1:MDMTagTagProperties[starts-with(ns1:Key,'register.Id')]">
            <ns5:Register>
                <ns5:RegisterId>
                     <xsl:value-of select="ns1:Value" />
                </ns5:RegisterId>
                <ns5:RegisterType>
                    <xsl:value-of select="key('tags', concat('register.RegisterType.', ns1:Value))/ns1:Value" />
                </ns5:RegisterType>
                <ns5:RegisterMultiplicationFactor>
                    <xsl:value-of select="key('tags', concat('register.MultiplicationFactor.', ns1:Value))/ns1:Value" />
                </ns5:RegisterMultiplicationFactor>
                <ns5:RegisterMeteringDirection>
                    <xsl:value-of select="key('tags', concat('register.MeteringDirection.', ns1:Value))/ns1:Value" />
                </ns5:RegisterMeteringDirection>
                <ns5:RegisterMeasureUnit>
                    <xsl:value-of select="key('tags', concat('register.MeasureUnit.', ns1:Value))/ns1:Value" />
                </ns5:RegisterMeasureUnit>
                 <ns5:RegisterNrOfDigits>
                    <xsl:value-of select="key('tags', concat('register.NrOfDigits.', ns1:Value))/ns1:Value" />
                </ns5:RegisterNrOfDigits>
            </ns5:Register>
        </xsl:for-each>
    </ns5:Output>
</xsl:template>
</xsl:stylesheet>

通过查看您的预期输出,您实际上可以使其更通用。试试这个XSLT:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ns1="http://www.test.org/cmm/xsd/mdmtag_01" xmlns:ns5="http://www.test.org/cmm/xsd/outputmdmtag_01" exclude-result-prefixes="ns1" version="1.0">
    <xsl:output method="xml" indent="yes" />

   <xsl:key name="tags" match="ns1:MDMTagTagProperties" use="substring-after(substring-after(ns1:Key, '.'), '.')" />

   <xsl:template match="/ns1:Properties">
    <ns5:Output>
        <xsl:for-each select="ns1:MDMTagTagProperties[contains(ns1:Key,'register.Id')]">
            <ns5:Register>
                <xsl:for-each select="key('tags', ns1:Value)">
                    <xsl:element name="ns5:Register{substring-before(substring-after(ns1:Key, '.'), '.')}">
                        <xsl:value-of select="ns1:Value" />
                    </xsl:element>
                </xsl:for-each>
            </ns5:Register>
        </xsl:for-each>
    </ns5:Output>
</xsl:template>
</xsl:stylesheet>

这只有在所有ns1:Key值的格式为“register.xxxxx.n.n.n”时才有效。

答案 1 :(得分:1)

作为替代方案,这里有一个XSLT 2.0分组方法:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs"
    xpath-default-namespace="http://www.test.org/cmm/xsd/mdmtag_01"
    xmlns:ns5="http://www.test.org/cmm/xsd/outputmdmtag_01" version="2.0">

    <xsl:param name="result-order" as="xs:string*"
        select="'register.Id', 'register.RegisterType', 'register.MultiplicationFactor', 'register.MeteringDirection', 'register.MeasureUnit'"/>

    <xsl:output indent="yes"/>

    <xsl:template match="Properties">
        <ns5:Output>
            <xsl:for-each-group select="MDMTagTagProperties"
                group-by="substring(Key, string-length(Key) - 4)">
                <ns5:Register>
                    <xsl:apply-templates select="current-group()">
                        <xsl:sort
                            select="index-of($result-order, substring(Key, 1, string-length(Key) - 6))"
                        />
                    </xsl:apply-templates>
                </ns5:Register>
            </xsl:for-each-group>
        </ns5:Output>
    </xsl:template>

    <xsl:template match="MDMTagTagProperties">
        <xsl:element name="ns5:{replace(Key, '\.[0-9]', '')}">
            <xsl:value-of select="Value"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>