Ниже приводится описание question posted here last year. Все еще будучи новичком, я борюсь (снова ...), чтобы преобразовать - используя XSLT 1.0 - следующий XML, который описывает объекты (обратите внимание на небольшое изменение ввода - «BC *» - на предыдущий вопрос):Последующие действия: создавать (грандиозные) элементы parent-child на основе разделителя в значениях атрибутов
<Data>
<Object>
<Property Name="Id" Value="001"/>
<Property Name="P.Id" Value="Id P"/>
<Property Name="P.Description" Value="Descr P"/>
<Property Name="A.Id" Value="Id A" />
<Property Name="A.Description" Value="Descr A"/>
<Property Name="B.Id" Value="Id B"/>
<Property Name="B.Description" Value="Descr B"/>
<Property Name="B.C.Id" Value="B.C.Id"/>
<Property Name="B.C.Description" Value="B.C.Description"/>
</Object>
</Data>
следующие правила должны применяться, чтобы получить желаемый результат:.
- для каждого «Property'-элемент, который делает не содержать разделитель»» в атрибуте «Имя», преобразуйте атрибут «Name» в дочерний элемент и выберите значение его атрибута «Значение».
- Для каждого элемента «Свойства», который делает, содержит разделители (ы) '.' в атрибуте «Имя», создайте:
- a) Родительский элемент (грандиозный) с использованием «подстроки перед» разделитель в атрибуте «Имя» - «рекурсивно до последнего появления» (не уверен, как описать, увидеть желаемый результат ниже) и
- b) дочерний элемент с использованием «подстроки-после» последний разделитель в атрибуте «Имя» и выберите значение его атрибута «Значение». Поэтому
Желательный результат должен выглядеть примерно так:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<ObjectData>
<Id>001</Id>
<P>
<Id>Id P</Id>
<Description>Descr P</Description>
</P>
<A>
<Id>Id A</Id>
<Description>Descr A</Description>
</A>
<B>
<Id>Id B</Id>
<Description>Descr B</Description>
<C>
<Id>B.C.Id</Id>
<Description>B.C.Description</C.Description>
</C>
</B>
</ObjectData>
</Root>
В настоящее время у меня есть следующий код:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="kPropertyByName" match="Property[contains(@Name, '.')]" use="concat(generate-id(..), '|', substring-before(@Name,'.'))"/>
<xsl:template match="Data">
<Root>
<xsl:apply-templates/>
</Root>
</xsl:template>
<xsl:template match="Object">
<ObjectData>
<xsl:apply-templates select="Property[not(contains(@Name, '.'))]"/>
<xsl:for-each select="Property[generate-id(.) =
generate-id(key('kPropertyByName',
concat(generate-id(..), '|', substring-before(@Name,'.')))[1])
] ">
<xsl:apply-templates select="." mode="parent"/>
</xsl:for-each>
</ObjectData>
</xsl:template>
<xsl:template match="Property[not(contains(@Name, '.'))]">
<xsl:element name="{@Name}">
<xsl:value-of select="@Value"/>
</xsl:element>
</xsl:template>
<xsl:template match="Property[(contains(@Name, '.'))]" mode="parent">
<xsl:element name="{substring-before(@Name,'.')}">
<xsl:apply-templates mode="child" select="../Property[
substring-before(current()/@Name,'.') =
substring-before(./@Name,'.')]"/>
</xsl:element>
</xsl:template>
<xsl:template match="Property[(contains(@Name, '.'))]" mode="child">
<xsl:element name="{substring-after(@Name,'.')}">
<xsl:value-of select="@Value"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
который дает мне следующий вывод - имеющий (нежелательную) «неразделенные» C. * - элементы:
<?xml version="1.0" encoding="UTF-8"?>
<Root>
<ObjectData>
<Id>001</Id>
<P>
<Id>Id P</Id>
<Description>Descr P</Description>
</P>
<A>
<Id>Id A</Id>
<Description>Descr A</Description>
</A>
<B>
<Id>Id B</Id>
<Description>Descr B</Description>
<C.Id>B.C.Id</C.Id>
<C.Description>B.C.Description</C.Description>
</B>
</ObjectData>
</Root>
Не то, что я ищу ... Любая помощь будет очень признательна!
Я не думаю, что ваш вывод следует ваши правила.Например, вы не ** создали родительский элемент B для 'Name =" B.C.Id "'; вы использовали ранее созданный элемент B для 'Name =" B.Id "'. Если вы не добавите еще каких-либо ограничений, эта проблема не определена. –
Это также поможет узнать, какой именно процессор XSLt 1.0 вы используете. Поскольку вход содержит данные с разделителями-точками (вместо правильной разметки XML), вы могли бы сэкономить много работы, используя некоторые функции расширения - если ваш процессор сможет их поддерживать. –
Что касается вашего первого замечания, вы на самом деле правы; простите за это. В принципе: элементы нужно создавать иерархически, используя строки до/после разделителя. Если строка не содержит разделителя, тогда создайте элемент as-is. Если родительский элемент «будет создан» уже существует, не создавайте его, а продолжайте его создание (ren) (правило 2). Надеюсь, это прояснит проблему. – user25160809