使用 XSLT 转换特定 XML 文档
您好,
我的 XML 文档具有以下布局
<root>
<child>
<item type="ID">id1</item>
<item type="TEXT">text1</item>
</child>
<child>
<item type="ID"/>
<item type="TEXT">text2</item>
</child>
<child>
<item type="ID"/>
<item type="TEXT">text3</item>
</child>
<child>
<item type="ID">id2</item>
<item type="TEXT">text4</item>
</child>
<child>
<item type="ID"/>
<item type="TEXT">text5</item>
</child>
...
</root>
每次出现 type=ID 的空项目标记时,这意味着它与前面的同级具有相同的值。现在我想将其转换为
<root>
<child id="id1">text1text2text3</child>
<child id="id2">text4text5</child>
...
</root>
我的解决方案,
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:apply-templates select="//child/item[@type='ID'][text()='id1' or text()='id2']"/>
</root>
</xsl:template>
<xsl:template match="child/item[text()='id1' or text()='id2']">
<child id="{text()}">
<xsl:value-of select="./../item[@type='TEXT']/."/>
<xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/>
</child>
</xsl:template>
<xsl:template match="child/item[not(text()='id1' or text()='id2')]">
<xsl:value-of select="./../item[@type='TEXT']/."/>
<xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/>
</xsl:template>
</xsl:stylesheet>
它有效,但丑陋且不灵活。例如,如果我有任意 id 值,而不仅仅是 id1 和 id2,该怎么办?有人有好的建议或更好的解决方案吗?
HI
my XML documents have the following layout
<root>
<child>
<item type="ID">id1</item>
<item type="TEXT">text1</item>
</child>
<child>
<item type="ID"/>
<item type="TEXT">text2</item>
</child>
<child>
<item type="ID"/>
<item type="TEXT">text3</item>
</child>
<child>
<item type="ID">id2</item>
<item type="TEXT">text4</item>
</child>
<child>
<item type="ID"/>
<item type="TEXT">text5</item>
</child>
...
</root>
Everytime there is an empty item tag with type=ID, it means that it has the same value as the preceding sibling. Now i want to transform this into
<root>
<child id="id1">text1text2text3</child>
<child id="id2">text4text5</child>
...
</root>
My solution to this is
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<root>
<xsl:apply-templates select="//child/item[@type='ID'][text()='id1' or text()='id2']"/>
</root>
</xsl:template>
<xsl:template match="child/item[text()='id1' or text()='id2']">
<child id="{text()}">
<xsl:value-of select="./../item[@type='TEXT']/."/>
<xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/>
</child>
</xsl:template>
<xsl:template match="child/item[not(text()='id1' or text()='id2')]">
<xsl:value-of select="./../item[@type='TEXT']/."/>
<xsl:apply-templates select="./../following::*[1]/item[@type='ID'][not(text()='id1' or text()='id2')]"/>
</xsl:template>
</xsl:stylesheet>
It works but is ugly and unflexible. For example what if i had arbitrary id values and not only id1 and id2. Does anybody has a good advice or a better solution?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
这个 XSLT 1.0 样式表应该可以做到这一点:
This XSLT 1.0 stylesheet should do it:
XSLT 2.0解决方案:
XSLT 2.0 solution:
此 XSLT 1.0 转换:
应用于提供的 XML 文档时:
产生所需的正确结果:
说明:使用键来表达所有匹配的
item
元素与前面带有@type='ID'
的第一个item
和子文本节点之间的关系。This XSLT 1.0 transformation:
when applied on the provided XML document:
produces the wanted, correct result:
Explanation: Using a key to express the relationship between all matched
item
elements to the first precedingitem
with@type='ID'
and a child text node.