Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Xml xsl标识符与索引的相关性_Xml_Xslt - Fatal编程技术网

Xml xsl标识符与索引的相关性

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

我有一个xml,其中包含人员列表、他们的数据库ID以及他们之间的关系列表。看起来是这样的:

<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>.&#10;</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