/ / Wyodrębnij xml z powtarzających się elementów w oparciu o unikatowy łańcuch podrzędny w wartości - xml, xslt, xslt-1.0, xslt-2.0

Wyodrębnij xml z powtarzających się elementów w oparciu o unikatowy łańcuch podrzędny w wartości - xml, xslt, xslt-1.0, xslt-2.0

Próbuję utworzyć strukturę XML, która ma powtarzalny element na podstawie danych wejściowych xml. W wejściowym powtarzającym się elemencie MDMTagTagProperties ma tylko 2 pola Key i Value. Na podstawie pola Kluczowego musimy utworzyć element w wyjściowym pliku xml i ustawić zawartość Value pole do tego. Ostatnie 3 cyfry znaku Key pole jest takie samo dla jednego podzbioru. Poniżej znajdują się dane wejściowe XML, xslt, które próbuję i pożądane dane wyjściowe.

Wkład:

<?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>

Oczekiwany wynik:

<?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>

Każda pomoc byłaby wielką przysługą.

Odpowiedzi:

1 dla odpowiedzi № 1

Rozważ użycie klucza do wyszukania innych wartości z wejściowego XML

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

Na przykład, aby wyszukać MultiplicationFactor zrobiłbyś to:

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

Wypróbuj ten 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>

Spoglądając na oczekiwane wyniki, można to uczynić bardziej ogólnym. Wypróbuj też 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>

To działałoby tylko, gdyby wszystkie ns1:Key wartości mają jednak postać "register.xxxxx.n.n.n".


1 dla odpowiedzi nr 2

Alternatywnie, tutaj jest podejście grupowania 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>