/ / XSLT, aby usunąć wszystkie oprócz niektórych węzłów z następującego typu struktury XML - xml, xslt

XSLT, aby usunąć wszystkie, ale niektóre węzły z następującej struktury XML - xml, xslt

<Rootnode>
<Properties Attribute ="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute ="xxx">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items>
<Item6>8</Item6>
</Items>
<Properties Attribute ="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>

Teraz chcę tylko TYLKO Właściwościi przedmioty. Najlepiej połączyć ze sobą grupy Właściwości i Elementy, jeśli Atrybuty mają tę samą nazwę i tę samą wartość, oraz SORTOWAĆ zarówno Właściwości, jak i Elementy na podstawie Atrybutów oraz posortować węzły podrzędne alfabetycznie. Do tej pory osiągnąłem puste; (

Wymagana wydajność jest prawie taka, jak pokazał ABach. Chociaż jedną rzeczą, o której zapomniałem wspomnieć, jest to, że mogą istnieć inne atrybuty dla każdej Właściwości lub Przedmiotów i że znam nazwę Atrybutu, na którym chcę sortować. Że mogę łatwo zmienić.

tj. wymagana wydajność

<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<xSize>10</xSize>
<xType>5</xType>
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item4>8</Item4>
<Item6>8</Item6>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>

I przepraszam za dotychczasowy wysiłek ... Skończyło się na właściwym bałaganie i nie sądziłem, że to bardzo by pomogło ... Jestem całkiem nowy w tych sprawach :)

Odpowiedzi:

2 dla odpowiedzi № 1

Jak już wskazał @LarsH, nie pokazując nam oczekiwanego wyjściowego pliku XML, pozostajemy zgadnąć, czego naprawdę chcesz. To powiedziawszy, oto moja próba rozwiązania XSLT 1.0.

Kiedy ten XSLT:

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

<xsl:key
name="PropertiesByAttributeNameVal"
match="Properties"
use="concat(name(@*[1]), "+", @*[1])" />

<xsl:key
name="ItemsByAttributeNameVal"
match="Items"
use="concat(name(@*[1]), "+", @*[1])" />

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

<xsl:template match="Rootnode">
<Rootnode>
<xsl:apply-templates
select="Properties[
generate-id() =
generate-id(key(
"PropertiesByAttributeNameVal",
concat(name(@*[1]), "+", @*[1]))[1])]">
<xsl:with-param name="pKeyName"
select=""PropertiesByAttributeNameVal"" />
<xsl:sort select="concat(name(@*[1]), "+", @*[1])" />
</xsl:apply-templates>
<xsl:apply-templates
select="Items[
generate-id() =
generate-id(key(
"ItemsByAttributeNameVal",
concat(name(@*[1]), "+", @*[1]))[1])]">
<xsl:with-param name="pKeyName"
select=""ItemsByAttributeNameVal"" />
<xsl:sort select="concat(name(@*[1]), "+", @*[1])" />
</xsl:apply-templates>
</Rootnode>
</xsl:template>

<xsl:template match="Properties|Items">
<xsl:param name="pKeyName" />
<xsl:copy>
<xsl:apply-templates select="@*" />
<xsl:apply-templates
select="key($pKeyName, concat(name(@*[1]), "+", @*[1]))/*">
<xsl:sort select="name()" />
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

... uruchom z dostarczonym plikiem XML:

<Rootnode>
<Properties Attribute="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute="xxx">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items>
<Item6>8</Item6>
</Items>
<Properties Attribute="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>

... myślę, że poprawne dane wyjściowe XML jest generowany:

<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<xSize>10</xSize>
<xType>5</xType>
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item4>8</Item4>
<Item6>8</Item6>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>

Pamiętaj, że jeśli ten sam XSLT jest uruchamiany na nieco zmodyfikowanym dokumencie XML (który ma więcej grupowań itp.):

<?xml version="1.0" encoding="utf-8"?>
<Rootnode>
<Properties Attribute="xxx">
<Type>1</Type>
<Size>10</Size>
</Properties>
<Other>
<blah>h</blah>
</Other>
<Other2>
<blah>h</blah>
</Other2>
<Properties Attribute="yyy">
<xType>5</xType>
<xSize>10</xSize>
</Properties>
<Items>
<Item4>8</Item4>
</Items>
<Items place="US">
<Item9>8</Item9>
</Items>
<Items>
<Item1>8</Item1>
</Items>
<Properties Attribute2="xxx">
<zType>1</zType>
<zSize>10</zSize>
</Properties>
<Properties Attribute="xxx">
<elephantType>5</elephantType>
<elephantSize>15</elephantSize>
</Properties>
<Items place="UK">
<Item1>8</Item1>
</Items>
</Rootnode>

... znowu, zakładam, że otrzymano prawidłową odpowiedź:

<?xml version="1.0"?>
<Rootnode>
<Properties Attribute="xxx">
<Size>10</Size>
<Type>1</Type>
<elephantSize>15</elephantSize>
<elephantType>5</elephantType>
</Properties>
<Properties Attribute="yyy">
<xSize>10</xSize>
<xType>5</xType>
</Properties>
<Properties Attribute2="xxx">
<zSize>10</zSize>
<zType>1</zType>
</Properties>
<Items>
<Item1>8</Item1>
<Item4>8</Item4>
</Items>
<Items place="UK">
<Item1>8</Item1>
</Items>
<Items place="US">
<Item9>8</Item9>
</Items>
</Rootnode>

Założenia:

  • Zakładam, że każdy <Properties> i <Items> element ma tylko jeden atrybut i powinien to być determinant grupowania.
  • Jeśli powyższe nie jest prawdą, przynajmniej zakładam, że pierwszym atrybutem tego elementu powinien być determinant grupowania.

Wyjaśnienie:

  1. Ponieważ jest to rozwiązanie XSLT 1.0, Muenchian Grouping jest kolejnością dnia, w której grupowanie węzłów i atrybutów w ramach unikalnych selektorów; dlatego definiujemy dwa klucze: jeden dla <Properties> elementy i jeden dla <Items> elementy.

  2. Pierwszy szablon to Identity Transform - jego zadaniem jest wyprowadzenie wszystkich węzłów i atrybutów z dokumentu źródłowego do dokumentu wynikowego w niezmienionej postaci.

  3. Drugi szablon pasuje do <Rootnode> element. Poleca się stosowanie szablonów tylko do tych <Properties> i <Items> elementy, które jako pierwsze pojawiają się w odpowiednich klawiszach; ma to zamierzony efekt przetwarzania tylko unikatowych elementów (na podstawie nazwy i wartości ich pierwszego atrybutu).

    Kiedy <xsl:apply-templates> element jest określony, należy pamiętać, że w obu przypadkach nakazuje się sortowanie wyników według tej samej pary nazwa / wartość atrybutu.

    Zauważ, że każdy <xsl:apply-templates> element otrzymuje parametr (przez <xsl:with-param>). Jak zobaczysz, kod do przetworzenia obu <Properties> i <Items> elementy są prawie identyczne; jedyna różnicajest kluczem, z którego czerpiemy wyniki. Z tego powodu postanowiłem skonsolidować tę logikę w trzecim szablonie i uwzględnić zmienność za pomocą tego parametru.

  4. Trzeci szablon pasuje do obu <Properties> i <Items> elementy. Dla każdego oryginalny węzeł jest kopiowany (podobnie jak jego atrybuty). Na koniec szablony są stosowane wobec wszystkich elementów potomnych tego elementu (z zachowaniem odpowiedniego sortowania [tym razem na podstawie nazwy samego elementu potomnego]).


1 dla odpowiedzi nr 2

Bardziej prawdopodobne jest, że otrzymasz pomoc, jeśli masz już coś, niż nic. Aby rozpocząć, utwórz szablon, który będzie pasował do właściwości i elementów (match="Properties | Items"), którego treść kopiuje tylko dopasowany element: <xsl:copy-of select="." />.

To da ci jakiś działający kod do pokazania.

Następnym krokiem, który zasugerowałbym, jest opublikowanie próbki pożądanego wyniku i faktycznego wyniku podanego przez kod XSLT.

Zapewni to znacznie mniejszą lukę dla osób, które mogą wypełnić odpowiedź na twoje pytanie.