XSL-идентификатор для индекса корреляции - PullRequest
2 голосов
/ 26 января 2012

У меня есть xml со списком людей, их идентификаторами базы данных и списком отношений между ними. Это выглядит так:

<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>

Я хотел бы сгенерировать, используя xslt 1.0 из Java, следующее:

person 2 relates to person 1.

Логика состоит в том, чтобы показать индекс человека на основе порядка, в котором он указан в xml.

Мои текущие идеи:

  • предварительно обрабатывает xml в java и отправляет карту как параметр в xsl с помощью [person_id, person_index], а затем для каждого отношения получает person_index из person_id
  • создание xpath в xsl, который находит индекс человека по данному идентификатору (хотя я не знаю, как создать xpath для этого)
  • предварительная обработка в java и создание карты, размещение ее в переменной ThreadLocal, а затем из xsl вызов другого метода, который использует этот ThreadLocal для получения индекса человека из идентификатора человека

Любые другие идеи, надеюсь, более простые, очень ценятся.

Спасибо!

Ответы [ 3 ]

1 голос
/ 26 января 2012

Я уверен, что должен быть лучший способ, но он работает:

Ответ на полезный совет от Dimitre - Обратите внимание, что это решение основано на возможности использовать XLST 2.0.В XLST 1.0 переменные являются «фрагментами дерева результатов», и вы не можете затем использовать их и добавлять к ним xpath без использования таких расширений, как saxon: parse.

<?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>
1 голос
/ 26 января 2012

Это преобразование (работает с отношениями с двумя или более лицами):

<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>

при применении к предоставленному документу XML (добавлено третье лицо, чтобы сделать его более интересным)

<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
1 голос
/ 26 января 2012

Нет необходимости в предварительной обработке или отображении 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>

Это сгенерирует одну строку текста для каждого <rel>. Это не полная таблица стилей, а остальное я оставлю вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...