#xml #xslt
#xml #xslt
Вопрос:
Мне нужна помощь в том, чтобы включить некоторые родственные узлы после имени узла в node extraInfo в следующем xml:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<BatchMember>
<Member>
<FirstName>MICHAEL </FirstName>
<Books>
<Fiction>1</Fiction>
<ChildrensBooks> </ChildrensBooks>
</Books>
<Stationery>
<Art> </Art>
<Writing> </Writing>
</Stationery>
<CardsGifts>1</CardsGifts>
<ROINI>1</ROINI>
<Signed>1</Signed>
<Date>2011-10-04</Date>
</Member>
<Member>
<FirstName>JOHN </FirstName>
<Books>
<Fiction>1</Fiction>
<ChildrensBooks> </ChildrensBooks>
</Books>
<Stationery>
<Art>1</Art>
<Writing> </Writing>
</Stationery>
<CardsGifts>1</CardsGifts>
<ROINI> </ROINI>
<Signed>1</Signed>
<Date>2011-10-04</Date>
</Member>
</BatchMember>
Я использовал следующий файл xsl:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:strip-space elements="FirstName Surname Add1 Add2 City Email"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BatchMember" >
<xsl:variable name="newline">
<xsl:text>
</xsl:text>
</xsl:variable>
<Batch>
<xsl:element name="Version" >1.0</xsl:element>
<xsl:copy>
<xsl:apply-templates />
</xsl:copy>
</Batch>
</xsl:template>
<xsl:strip-space elements="*"/>
<xsl:key name="kFollowing" match="FirstName" use="generate-id(preceding-sibling::*[not(self::b)][1])"/>
<xsl:template match="FirstName[not(preceding-sibling::*[1][self::FirstName])]">
<ExtraInfo>
<xsl:copy-of select="key('kFollowing', generate-id(preceding-sibling::*[1]))"/>
</ExtraInfo>
</xsl:template>
<xsl:template match="FirstName"/>
<xsl:param name="true-text" select="'True'"/>
<xsl:param name="false-text" select="'False'"/>
<xsl:template match="FirstName">
</xsl:template>
<xsl:template match="Books">
<Category>
<Name>Books</Name>
<xsl:choose>
<xsl:when test="Fiction = 1">
<Fiction>
<xsl:value-of select="$true-text"/>
</Fiction>
</xsl:when>
<xsl:otherwise>
<Fiction>
<xsl:value-of select="$false-text"/>
</Fiction>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="ChildrensBooks = 1">
<ChildrensBooks>
<xsl:value-of select="$true-text"/>
</ChildrensBooks>
</xsl:when>
<xsl:otherwise>
<ChildrensBooks>
<xsl:value-of select="$false-text"/>
</ChildrensBooks>
</xsl:otherwise>
</xsl:choose>
</Category>
</xsl:template>
<xsl:template match="Stationery">
<Category>
<Name>Stationery</Name>
<xsl:choose>
<xsl:when test="Art = 1">
<Art>
<xsl:value-of select="$true-text"/>
</Art>
</xsl:when>
<xsl:otherwise>
<Art>
<xsl:value-of select="$false-text"/>
</Art>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="Writing = 1">
<Writing>
<xsl:value-of select="$true-text"/>
</Writing>
</xsl:when>
<xsl:otherwise>
<Writing>
<xsl:value-of select="$false-text"/>
</Writing>
</xsl:otherwise>
</xsl:choose>
</Category>
</xsl:template>
<xsl:template match="CardsGifts">
</xsl:template>
</xsl:stylesheet>
Что привело к следующему результату:
<?xml version="1.0" ?>
- <Batch>
<Version>1.0</Version>
- <BatchMember>
- <Member>
- <ExtraInfo>
<FirstName>MICHAEL</FirstName>
<FirstName>JOHN</FirstName>
</ExtraInfo>
- <Category>
<Name>Books</Name>
<Fiction>True</Fiction>
<ChildrensBooks>False</ChildrensBooks>
</Category>
- <Category>
<Name>Stationery</Name>
<Art>False</Art>
<Writing>False</Writing>
</Category>
<ROINI>1</ROINI>
<Signed>1</Signed>
<Date>2011-10-04</Date>
</Member>
- <Member>
- <ExtraInfo>
<FirstName>MICHAEL</FirstName>
<FirstName>JOHN</FirstName>
</ExtraInfo>
- <Category>
<Name>Books</Name>
<Fiction>True</Fiction>
<ChildrensBooks>False</ChildrensBooks>
</Category>
- <Category>
<Name>Stationery</Name>
<Art>True</Art>
<Writing>False</Writing>
</Category>
<ROINI />
<Signed>1</Signed>
<Date>2011-10-04</Date>
</Member>
</BatchMember>
</Batch>
Это тот результат, который мне нужен:
<?xml version="1.0"?>
<BatchMember>
<Version>1.0</Version>
<Member>
<FirstName>MICHAEL</FirstName>
<ExtraInfo>
<Category>
<Name>Books</Name>
<attribute>
<Name>Fiction</Name>
<Value>True</Value>
</attribute>
<attribute>
<Name>Children's</Name>
<Value>False</Value>
</attribute>
</Category>
<Category>
<Name>Stationery</Name>
<attribute>
<Name>Art</Name>
<Value>False</Value>
</attribute>
<attribute>
<Name>Writing</Name>
<Value>False</Value>
</attribute>
</Category>
</ExtraInfo>
</Member>
<Member>
<FirstName>JOHN</FirstName>
<ExtraInfo>
<Category>
<Name>Books</Name>
<attribute>
<Name>Fiction</Name>
<Value>True</Value>
</attribute>
<attribute>
<Name>Children's</Name>
<Value>False</Value>
</attribute>
</Category>
<Category>
<Name>Stationery</Name>
<attribute>
<Name>Art</Name>
<Value>True</Value>
</attribute>
<attribute>
<Name>Writing</Name>
<Value>False</Value>
</attribute>
</Category>
<ExtraInfo>
</Member>
</BatchMember>
Что я делаю не так?
С уважением
Джефф.
Комментарии:
1. Я хотел сказать, что желаемый результат:
2. Отредактируйте свой пост и покажите нужный XML
3. Теперь я ввел желаемый xml
Ответ №1:
Я думаю, что ваш XSLT может чрезмерно усложнять ситуацию. Например, вам не обязательно нужен ключ xsl:.
Что вы могли бы сделать, так это когда вы сопоставляете элемент Member, добавьте некоторую специальную кодировку для элемента FirstName, чтобы скопировать его, а затем просто продолжайте сопоставлять все дочерние элементы
<xsl:template match="Member">
<xsl:copy>
<xsl:copy-of select="FirstName"/>
<ExtraInfo>
<xsl:apply-templates />
</ExtraInfo>
</xsl:copy>
</xsl:template>
Однако вам понадобится пустой шаблон, чтобы снова сопоставить элемент FirstName, чтобы избежать его повторного вывода
<xsl:template match="FirstName" />
Вам также понадобятся соответствующие шаблоны для вашей книги и стационарных элементов, чтобы выполнить специальную обработку для них
<xsl:template match="Books|Stationery">
<Category>
<Name>
<xsl:value-of select="local-name()"/>
</Name>
<xsl:apply-templates select="*" mode="Attributes"/>
</Category>
</xsl:template>
Вам также понадобится шаблон для обработки дочерних элементов книги и стационарных элементов. Я не уверен на 100%, что вы хотели с этим сделать, но в вашем ожидаемом результате, похоже, вы хотели преобразовать их в элементы атрибутов.
Вот XSLT в полном объеме
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ex="http://exslt.org/dates-and-times" extension-element-prefixes="ex">
<xsl:strip-space elements="FirstName Surname Add1 Add2 City Email"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="BatchMember">
<Batch>
<Version>1.0</Version>
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</Batch>
</xsl:template>
<xsl:template match="Member">
<xsl:copy>
<xsl:copy-of select="FirstName"/>
<ExtraInfo>
<xsl:apply-templates />
</ExtraInfo>
</xsl:copy>
</xsl:template>
<xsl:template match="FirstName" />
<xsl:template match="Books|Stationery">
<Category>
<Name>
<xsl:value-of select="local-name()"/>
</Name>
<xsl:apply-templates select="*" mode="Attributes"/>
</Category>
</xsl:template>
<xsl:template match="*" mode="Attributes">
<attribute>
<Name>
<xsl:value-of select="local-name()"/>
</Name>
<Value>
<xsl:choose>
<xsl:when test=". = 1">True</xsl:when>
<xsl:otherwise>False</xsl:otherwise>
</xsl:choose>
</Value>
</attribute>
</xsl:template>
</xsl:stylesheet>
При применении к вашему образцу входного XML выводится следующее:
<Batch>
<Version>1.0</Version>
<BatchMember>
<Member>
<FirstName>MICHAEL </FirstName>
<ExtraInfo>
<Category>
<Name>Books</Name>
<attribute>
<Name>Fiction</Name>
<Value>True</Value>
</attribute>
<attribute>
<Name>ChildrensBooks</Name>
<Value>False</Value>
</attribute>
</Category>
<Category>
<Name>Stationery</Name>
<attribute>
<Name>Art</Name>
<Value>False</Value>
</attribute>
<attribute>
<Name>Writing</Name>
<Value>False</Value>
</attribute>
</Category>
<CardsGifts>1</CardsGifts>
<ROINI>1</ROINI>
<Signed>1</Signed>
<Date>2011-10-04</Date>
</ExtraInfo>
</Member>
<Member>
<FirstName>JOHN </FirstName>
<ExtraInfo>
<Category>
<Name>Books</Name>
<attribute>
<Name>Fiction</Name>
<Value>True</Value>
</attribute>
<attribute>
<Name>ChildrensBooks</Name>
<Value>False</Value>
</attribute>
</Category>
<Category>
<Name>Stationery</Name>
<attribute>
<Name>Art</Name>
<Value>True</Value>
</attribute>
<attribute>
<Name>Writing</Name>
<Value>False</Value>
</attribute>
</Category>
<CardsGifts>1</CardsGifts>
<ROINI/>
<Signed>1</Signed>
<Date>2011-10-04</Date>
</ExtraInfo>
</Member>
</BatchMember>
</Batch>
Хотя это не совсем соответствует вашему ожидаемому результату (например, он по-прежнему выводит элементы CardsGifts), я надеюсь, что это может дать вам что-то для работы.