Xml xsl标识符与索引的相关性
我有一个xml,其中包含人员列表、他们的数据库ID以及他们之间的关系列表。看起来是这样的:Xml xsl标识符与索引的相关性,xml,xslt,Xml,Xslt,我有一个xml,其中包含人员列表、他们的数据库ID以及他们之间的关系列表。看起来是这样的: <root> <person> <id>1000</id> <name>p1</name> </person> <person> <id>1001</id> <name>p2</name> </person&g
<root>
<person>
<id>1000</id>
<name>p1</name>
</person>
<person>
<id>1001</id>
<name>p2</name>
</person>
<rel>
<personid>1001</personid>
<personid>1000</personid>
</rel>
</root>
逻辑是根据人员在xml中出现的顺序显示其索引
我目前的想法:
- 在java中预处理xml,并将映射作为参数发送到带有[person_id,person_index]的xsl,然后针对每个关系从person_id获取person_索引
- 在xsl中生成一个xpath,该xpath通过给定id查找个人的索引(尽管我不知道如何为此构造xpath)
- 在java中进行预处理并构造映射,将其放置在ThreadLocal变量中,然后从xsl调用另一个使用此ThreadLocal从person id获取person索引的方法
谢谢 不需要Java预处理或映射
<xsl:key name="kPersonById" match="person" use="id" />
<xsl:template match="rel">
<xsl:text>Person </xsl:text>
<xsl:value-of select="key('kPersonById', personid[1])/name" />
<xsl:text> relates to </xsl:text>
<xsl:value-of select="key('kPersonById', personid[2])/name" />
<xsl:text>. </xsl:text>
</xsl:template>
人
涉及
.
这将为每个
生成一行文本。这不是一个完整的样式表,我将把剩下的留给您解决。我相信一定有更好的方法,但这很有效:
回复Dimitre的建议-请注意,此解决方案依赖于能够使用XLST 2.0。在XLST1.0中,变量是“结果树片段”,如果不使用诸如saxon:parse之类的扩展,就不能使用它们并向它们添加XPath
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:variable name="indexed">
<xsl:apply-templates select="root/person"/>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="root/rel"/>
</xsl:template>
<xsl:template match="root/person">
<xsl:copy>
<index>
<!-- concern - will this make the approach take O(n^2) and
therefore get very slow for large input docs -->
<xsl:number/>
</index>
<xsl:copy-of select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/rel">
<xsl:variable name="p1" select="personid[1]/text()"/>
<xsl:variable name="p2" select="personid[2]/text()"/>
<xsl:text>Person </xsl:text>
<xsl:value-of select="$indexed/person[id = $p1]/index"/>
<xsl:text> relates to person </xsl:text>
<xsl:value-of select="$indexed/person[id = $p2]/index"/>
</xsl:template>
</xsl:stylesheet>
人
与某人有关
此转换(适用于两人或多人的关系):
这不能回答这个问题,但是您可以考虑使用单个数据字段的属性。例如,您可能会选择。更容易阅读,也更容易用SAX进行解析。谢谢,我实际上不控制xml结构,它来自不同的应用程序。很抱歉混淆了,但是person 1指的是xml顺序为1的人。我不想使用名称标记值(p1)。“有可能吗?”丹:当然有。使用
“key(…)/count(前面的兄弟姐妹::person)+1”
这似乎是一种很好且简单的方法。感谢您的快速回复。谢谢!请在回答中提到这是一个XSLT2.0解决方案——否则很少(如果有的话)人会注意到这一重要事实。因为您几乎没有使用XSLT2.0中的任何内容,为什么不尝试生成XSLT1.0解决方案(或真正的XSLT2.0解决方案)?最后,对于大量的person
和rel
元素来说,这个解决方案可能会比较慢。当我最终理解你在这里做什么时,Dimitre,我突然大笑起来——非常聪明——这对一个新手来说并不明显——我相信你能比我更好地解释你的解决方案——确实非常聪明,这是一种很好的解决多元素关系的方法。但是,我不确定match=text()的最后一个模板的作用。谢谢@dan leadgy:template
消除了文档中的任何文本节点的输出——否则,由于XSLT处理模型,这种情况会发生——使用XSLT内置模板会导致输出XSLT文档中的所有文本节点。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:variable name="indexed">
<xsl:apply-templates select="root/person"/>
</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates select="root/rel"/>
</xsl:template>
<xsl:template match="root/person">
<xsl:copy>
<index>
<!-- concern - will this make the approach take O(n^2) and
therefore get very slow for large input docs -->
<xsl:number/>
</index>
<xsl:copy-of select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root/rel">
<xsl:variable name="p1" select="personid[1]/text()"/>
<xsl:variable name="p2" select="personid[2]/text()"/>
<xsl:text>Person </xsl:text>
<xsl:value-of select="$indexed/person[id = $p1]/index"/>
<xsl:text> relates to person </xsl:text>
<xsl:value-of select="$indexed/person[id = $p2]/index"/>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kPersonById" match="person" use="id"/>
<xsl:template match="rel/personid">
<xsl:variable name="vPersInd" select=
"count(key('kPersonById', .)
/preceding-sibling::person
)
+1 "/>
<xsl:text> is related to person </xsl:text>
<xsl:value-of select="$vPersInd"/>
</xsl:template>
<xsl:template match="rel/personid[1]">
<xsl:variable name="vPersInd" select=
"count(key('kPersonById', .)
/preceding-sibling::person
)
+1 "/>
person <xsl:value-of select="$vPersInd"/><xsl:text/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
<root>
<person>
<id>1000</id>
<name>p1</name>
</person>
<person>
<id>1001</id>
<name>p2</name>
</person>
<person>
<id>1002</id>
<name>p3</name>
</person>
<rel>
<personid>1001</personid>
<personid>1000</personid>
<personid>1002</personid>
</rel>
</root>
person 2 is related to person 1 is related to person 3