Перейти к использованию XSLT - PullRequest
3 голосов
/ 31 августа 2011

Я получаю XML-документ от третьей стороны (поэтому я не могу его изменить), который содержит около 1000 записей. Я перевожу это, используя XSLT, чтобы показывать пользователю только 50 записей одновременно. Я могу контролировать, какие записи показываются, проверяя положение, например,

xsl:if test="not(position() < 101)"

xsl:if test="position() < 150"

Пользователь предпочел бы перейти к значению, а не прокручивать страницу за страницей, пока не найдет его. Остальные записи должны отображаться после перехода к значению, поэтому я не хочу проверять точное совпадение. Сначала я думал, что смогу сравнить строки, например

xsl:if test="@key >= 'jumpto'"

но это не поддерживается в 1.0. Есть идеи, как добиться того, чего я хочу?

XML достаточно велик для публикации, и данные являются конфиденциальными. Но представьте, что это простой XML-файл с именем, например,

<contacts>
    <name>alan</name>
    <name>brad</name>
    <name>chad</name>
    <name>dave</name>
    <name>eric</name>
</contacts>

Я хочу показать только данные, начиная с Дейва, и могу передать Дэйва в документ XSL.

Ответы [ 3 ]

2 голосов
/ 31 августа 2011

XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:param name="p">dave</xsl:param>

  <xsl:template match="contacts">
    <out>
      <xsl:apply-templates 
        select="name[. = $p] | name[. = $p]/following-sibling::name"/>
    </out>
  </xsl:template>

  <xsl:template match="name">
    <xsl:copy-of select="."/>
  </xsl:template>

</xsl:stylesheet>

Выход:

<out>
  <name>dave</name>
  <name>eric</name>
</out>
0 голосов
/ 01 сентября 2011

Я думаю, вам нужно что-то вроде этого (я предполагаю, что name s отсортированы, и вы хотите показать все name элементы, начиная с первого, чье значение больше или равно значению 'dave'):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:my="my:my">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <my:Start>dave</my:Start>

 <xsl:param name="pStart" select="document('')/*/my:Start"/>

 <xsl:template match="name">
  <xsl:variable name="vThis" select="."/>

  <xsl:for-each select=". | $pStart">
   <xsl:sort/>

   <xsl:if test=
    "position() = 2 and . = $vThis">
    <xsl:copy-of select="$vThis"/>
   </xsl:if>
  </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

Когда это преобразование применяется к предоставленному документу XML :

<contacts>
    <name>alan</name>
    <name>brad</name>
    <name>chad</name>
    <name>dave</name>
    <name>eric</name>
</contacts>

желаемый, правильный результат получается :

<name>dave</name>
<name>eric</name>

Если преобразование применяется к этому документу XML (примечание: name со значением 'dave'):

<contacts>
    <name>alan</name>
    <name>brad</name>
    <name>chad</name>
    <name>dave2</name>
    <name>eric</name>
</contacts>

снова правильный результат - каждый name со значением, большим или равным 'dave' - получается :

<name>dave2</name>
<name>eric</name>

Объяснение :

Здесь я продемонстрировал реализацию сравнения строк «XPath 1.0 + XSLT 1.0» для бедного человека.

Узлы, содержащие две строки, отсортированы. Затем узел во второй позиции имеет строковое значение, большее или равноеэто узла в первой позиции.

0 голосов
/ 31 августа 2011

следующее преобразование

  • использует правило идентификации, чтобы копировать все как есть (мы могли бы избежать здесь, но я подозреваю, что ваш ввод намного сложнее)
  • переопределяет элемент contacts и сохраняет только нужные имя узлы (узел с данным $onward или любой узел, для которого предыдущий брат или сестра name имеет данное $onward)

[XSLT 1.0]

 <xsl:stylesheet  version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:param name="onward" select="'dave'"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*" /> 
        </xsl:copy>
    </xsl:template>

    <xsl:template match="contacts">
        <xsl:copy>
            <xsl:apply-templates select="@* | 
                name[.=$onward or preceding-sibling::name=$onward]"/>
        </xsl:copy> 
    </xsl:template>

</xsl:stylesheet>

По умолчанию ($onward='dave') выдает:

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