#xml #xslt #grandchild
#xml #xslt #дочерний
Вопрос:
У меня есть структура XML как таковая:
<GetAccount_Output>
<GetAccountResponse>
<AccountCollection>
<Account>
<AccountId>1</AccountId>
</Account>
</AccountCollection>
</GetAccountResponse>
<GetAccountResponse>
<AccountCollection>
<Account>
<AccountId>2</AccountId>
</Account>
</AccountCollection>
</GetAccountResponse>
</GetAccount_Output>
Желаемый результат:
<GetAccount_Output>
<GetAccountResponse>
<AccountCollection>
<Account>
<AccountId>1</AccountId>
</Account>
<Account>
<AccountId>2</AccountId>
</Account>
</AccountCollection>
</GetAccountResponse>
</GetAccount_Output>
Я могу удалить один:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<GetAccountResponse>
<xsl:copy-of select="GetAccountResponse/*"/>
</GetAccountResponse>
<xsl:apply-templates select="*[name()!='GetAccountResponse']"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Выдача этого результата:
<GetAccount_Output>
<AccountCollection>
<Account>
<AccountId>1</AccountId>
</Account>
<Account>
<AccountId>2</AccountId>
</Account>
</AccountCollection>
</GetAccount_Output>
Но я не знаю, как я могу объединить оба GetAccountResponse
и AccountCollection
?
Кто-нибудь, кто может подтолкнуть меня к правильному решению?
Ответ №1:
Вот один из способов взглянуть на это:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="GetAccount_Output">
<GetAccount_Output>
<GetAccountResponse>
<AccountCollection>
<xsl:apply-templates select="GetAccountResponse"/>
</AccountCollection>
</GetAccountResponse>
</GetAccount_Output>
</xsl:template>
<xsl:template match="GetAccountResponse">
<xsl:apply-templates select="AccountCollection/Account"/>
</xsl:template>
</xsl:stylesheet>
—
Вот еще:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/">
<GetAccount_Output>
<GetAccountResponse>
<AccountCollection>
<xsl:for-each select="GetAccount_Output/GetAccountResponse/AccountCollection/Account">
<xsl:copy-of select="."/>
</xsl:for-each>
</AccountCollection>
</GetAccountResponse>
</GetAccount_Output>
</xsl:template>
</xsl:stylesheet>
Комментарии:
1. Черт возьми, я только начал писать по существу тот же ответ, когда ты опубликовал … 🙂 1 для тебя.
Ответ №2:
Вот немного другой способ сделать это:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Copy all nodes -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Ignore any GetAccountResponse except the first -->
<xsl:template match="GetAccountResponse[position() != 1]"/>
<!-- Include all Account in AccountCollection -->
<xsl:template match="AccountCollection">
<xsl:copy>
<xsl:apply-templates select="//Account"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>