我如何处理这个问题,以便在XML文件中连接类似的XML标签
我有以下格式的XMl ::
<addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<Descritpion>Hi</Descritpion>
<Descritpion>This is Chester </Descritpion>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
</address>
<address>
<first-name>Mary</first-name>
<Descritpion>Hi</Descritpion>
<Descritpion>This is Mary </Descritpion>
<Descritpion>Bye</Descritpion>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
</address>
</addressbook>
我需要以下面的格式,有人请为此建议XSLT。
<addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<Descritpion>Hi | This is Chester </Descritpion>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
</address>
<address>
<first-name>Mary</first-name>
<Descritpion>Hi | This is Mary | Bye</Descritpion>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
</address>
</addressbook>
答案 0 :(得分:1)
此转化:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="Descritpion[not(preceding-sibling::*[1][self::Descritpion])]">
<Descritpion>
<xsl:value-of select="."/>
<xsl:apply-templates select="following-sibling::Descritpion/text()"/>
</Descritpion>
</xsl:template>
<xsl:template match="Descritpion/text()">
<xsl:value-of select="concat(' | ', .)"/>
</xsl:template>
<xsl:template match="Descritpion"/>
</xsl:stylesheet>
应用于提供的XML文档时:
<addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<Descritpion>Hi</Descritpion>
<Descritpion>This is Chester </Descritpion>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
</address>
<address>
<first-name>Mary</first-name>
<Descritpion>Hi</Descritpion>
<Descritpion>This is Mary </Descritpion>
<Descritpion>Bye</Descritpion>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
</address>
</addressbook>
生成想要的正确结果:
<addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<Descritpion>Hi | This is Chester </Descritpion>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
</address>
<address>
<first-name>Mary</first-name>
<Descritpion>Hi | This is Mary | Bye</Descritpion>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
</address>
</addressbook>
<强>解释强>:
身份规则“按原样”复制每个节点。
Descritpion
匹配的空体模板覆盖身份模板,通常会忽略/删除 Descritpion
元素。
只有Descritpion
元素的前一个兄弟元素不是Descritpion
本身才会被另一个覆盖模板专门处理。这里复制元素的字符串值,然后将模板应用于以下兄弟Descritpion
元素的所有text-node-children。
匹配Descritpion
元素的text-node-child的模板实现了有用的文本连接。
答案 1 :(得分:0)
要做到这一点,你可以建立身份变换,但添加额外的规则来处理你感兴趣的元素
我认为您首先需要匹配其中没有子元素的元素
<xsl:template match="*[not(*)]" priority="1">
然后,您可以向此处添加代码以输出当前文本值,然后选择具有相同名称的所有后续兄弟姐妹的文本值(将使用之前的分隔符输出)
<xsl:apply-templates
select="following-sibling::*[local-name() = local-name(current())]/text()"
mode="concat"/>
您还需要添加一个模板来忽略与前一个兄弟同名的元素,这样它们就不会输出两次
<xsl:template
match="*[not(*)][local-name() = local-name(preceding-sibling::*[1])]"
priority="2" />
请注意此处使用优先级属性,因此XSLT处理器首先匹配优先级较高的处理器。
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="*[not(*)]" priority="1">
<xsl:copy>
<xsl:value-of select="normalize-space(.)"/>
<xsl:apply-templates select="following-sibling::*[local-name() = local-name(current())]/text()" mode="concat"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(*)][local-name() = local-name(preceding-sibling::*[1])]" priority="2"/>
<xsl:template match="text()" mode="concat">
<xsl:value-of select="concat(' | ', normalize-space(.))"/>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
当应用于您的示例XML时,输出以下内容
<addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<Descritpion>Hi | This is Chester</Descritpion>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
</address>
<address>
<first-name>Mary</first-name>
<Descritpion>Hi | This is Mary | Bye</Descritpion>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
</address>
</addressbook>
答案 2 :(得分:0)
这是另一种方法。
有一点需要注意:此解决方案不维护输出文档排序(即,它不会直接在<Descritpion>
元素下创建新的<first-name>
元素)。如果这对您很重要,请查看其他提供的解决方案。
<?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="*"/>
<!-- TEMPLATE #1 -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- TEMPLATE #2 -->
<xsl:template match="address">
<xsl:copy>
<xsl:apply-templates/>
<Descritpion>
<xsl:apply-templates select="Descritpion/text()"/>
</Descritpion>
</xsl:copy>
</xsl:template>
<!-- TEMPLATE #3 -->
<xsl:template match="Descritpion/text()">
<xsl:value-of select="." />
<xsl:if test="position() != last()"> | </xsl:if>
</xsl:template>
<!-- TEMPLATE #4 -->
<xsl:template match="Descritpion" />
</xsl:stylesheet>
在提供的XML文档上提供此内容时:
<?xml version="1.0" encoding="UTF-8"?>
<addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<Descritpion>Hi</Descritpion>
<Descritpion>This is Chester </Descritpion>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
</address>
<address>
<first-name>Mary</first-name>
<Descritpion>Hi</Descritpion>
<Descritpion>This is Mary </Descritpion>
<Descritpion>Bye</Descritpion>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
</address>
</addressbook>
...产生了所需的结果:
<?xml version="1.0" encoding="UTF-8"?><addressbook>
<address>
<first-name>Chester Hasbrouck</first-name>
<street>1234 Main Street</street>
<city>Sheboygan</city>
<state>WI</state>
<zip>48392</zip>
<Descritpion>Hi | This is Chester </Descritpion>
</address>
<address>
<first-name>Mary</first-name>
<street>283 First Avenue</street>
<city>Skunk Haven</city>
<state>MA</state>
<zip>02718</zip>
<Descritpion>Hi | This is Mary | Bye</Descritpion>
</address>
</addressbook>
<强>解释强>
模板#1:“身份模板”按原样复制所有内容。
模板#2:此模板按原样复制每个<address>
元素,创建新的<Descritpion>
元素,并指示XSLT处理器填充该元素包含与Descritpion/text()
匹配的任何模板的结果的新元素。
模板#3:此模板处理模板#2的结果;特别是,它复制了所有旧<Descritpion>
元素中的文本,并且在到达最后一个元素之前,在结果之间放置了|
。
模板#4:此模板会从源文档中删除原始<Descritpion>
元素。