Обратный инжиниринг неизвестного XML на основе известного XSL - PullRequest
2 голосов
/ 17 сентября 2010

Решено!

После того, как я последовал совету Матти, я удалил пользовательские функции и все хорошо.

Исходное сообщение:

Я новичок в XSLTна сегодняшний день, так что я уверен, что это не просто для многих из вас.В любом случае:

Мне было поручено создать виджет для веб-сайта моей компании, который использует данные, предоставленные сторонним поставщиком.

Поставщик отказывается отправить нам образец XMLfile (, даже пустой, только с тегами элемента! ), поэтому я пытаюсь воссоздать XML на основе того, что я вижу в XSLT, который они нам отправили.( насмешек в изобилии )

Это (раздетый) XSLT-файл, который нам отправили:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:myCustXslFunctions="urn:CustomXslFunctions">

  <xsl:variable name="NumberColumns" >1</xsl:variable>
  <xsl:variable name="PaperId" >1234567890ABCDEF</xsl:variable>

  <xsl:output method="html" version="1.0" encoding="UTF-8" indent="no" />
  <xsl:template match="/NewDataSet">
    <div><xsl:apply-templates select="/NewDataSet" mode="columns" /></div>
  </xsl:template>

  <xsl:template match="NewDataSet" mode="columns">
    <xsl:for-each select="Table[position() mod $NumberColumns  = 1 or $NumberColumns = 1]">
      <p>
        <xsl:for-each select=".|following-sibling::Table[position() &lt; $NumberColumns]">
          <span class="description">
            <xsl:element name="a">
              <xsl:attribute name="target">_blank</xsl:attribute>
              <xsl:attribute name="class" >description</xsl:attribute>
              <xsl:choose>
                <xsl:when test="retail='true'">
                  <xsl:attribute name="href">http://website/retail/?pid=<xsl:value-of select="$PaperId" />&#38;adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&#38;adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
                </xsl:otherwise>
              </xsl:choose>
              <xsl:choose>
                <xsl:when test="imageurl != ''">
                  <xsl:element name="img">
                    <xsl:attribute name="src"><xsl:value-of select="imageurl" /></xsl:attribute>
                    <xsl:attribute name="border">0</xsl:attribute>
                    <xsl:attribute name="class">thumbnail</xsl:attribute>
                  </xsl:element>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:element name="img">
                    <xsl:attribute name="src">http://website/thumbs/<xsl:value-of select="paperid" />_<xsl:value-of select="paperitemid" />_100.jpg</xsl:attribute>
                    <xsl:attribute name="border">0</xsl:attribute>
                    <xsl:attribute name="class">thumbnail</xsl:attribute>
                  </xsl:element>
                </xsl:otherwise>
              </xsl:choose>
              </xsl:element>
          </span>
        </xsl:for-each>
      </p>
      <p>
        <xsl:for-each select=".|following-sibling::Table[position() &lt; $NumberColumns]">
          <span class="description">
            <xsl:element name="a">
              <xsl:attribute name="target">_blank</xsl:attribute>
              <xsl:attribute name="class" >description</xsl:attribute>
              <xsl:choose>
                <xsl:when test="retail='true'">
                  <xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&#38;adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&#38;adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
                </xsl:otherwise>
              </xsl:choose>
              <xsl:choose>
                <xsl:when test="string-length(shortdescr) = 0"><xsl:value-of select="myCustXslFunctions:MakeNice(descr,20,20,'Left','true')" /></xsl:when>
                <xsl:otherwise><xsl:value-of select="myCustXslFunctions:MakeNice(shortdescr,20,20,'Left','true')" /></xsl:otherwise>
              </xsl:choose>
            </xsl:element>
          </span>
        </xsl:for-each>
      </p>
    </xsl:for-each>
  </xsl:template>
</xsl:transform>

И моя слабая попыткапри обратном инжиниринге XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="facepalm.xsl"?>
<NewDataSet>
  <Table>
    <paperid>123</paperid>
    <paperitemid>12345</paperitemid>
    <descr>facepalm of doom</descr>
    <shortdescr>facepalm</shortdescr>
    <retail>true</retail>
    <imageurl>http://website/facepalm.jpg</imageurl>
  </Table>
  <Table>
    <paperid>456</paperid>
    <paperitemid>67890</paperitemid>
    <descr>mega-sigh</descr>
    <shortdescr>sigh</shortdescr>
    <retail>true</retail>
    <imageurl>http://website/sigh.jpg</imageurl>
  </Table>
</NewDataSet>

У меня нет сомнений, что я упускаю из виду нечто простое, но мой статус новичка в XSLT уже сделал это многочасовымПроект.

Любая помощь с благодарностью.

Ответы [ 2 ]

2 голосов
/ 17 сентября 2010

Мое предположение было бы больше похоже на:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="facepalm.xsl"?>
<NewDataSet>
 <Table>
  <paperid>123</paperid>
  <paperitemid>12345</paperitemid>
  <descr>failvendor</descr>
  <shortdescr>facepalm</shortdescr>
  <retail>true</retail>
  <imageurl>http://website/facepalm.jpg</imageurl>
 </Table>
 <Table>
  <paperid>456</paperid>
  <paperitemid>67890</paperitemid>
  <descr>is fail</descr>
  <shortdescr>sigh</shortdescr>
  <retail>true</retail>
  <imageurl>http://website/sigh.jpg</imageurl>
 </Table>
</NewDataSet>
  1. Материал [] не относится к частям имени элемента, он относится к позиции элемента. Таким образом, имя элемента просто Table.
  2. Вы пропустили элементы descr и paperid.

Кажется, что XSLT делает размещение элементов в списке в столбцах. Да, это смешно сложно в XSLT.

Кроме того, может показаться, что он игнорирует paperid и paperitemid, если определено imageurl, и игнорирует descr, если предоставляется shortdescr. Это может помочь вам в вашем квесте.

... как вы должны это проверить без реального XML, кстати?

1 голос
/ 14 июня 2013

В общем случае невозможно определить структуру входного XML-файла, используя только XSLT

Несмотря на то, что в этом случае вы, возможно, смогли реверсировать XML-описание, основанное на XSLT, в общем случае это невозможно сделать правильно. В этом случае это было возможно, потому что шаблон был маленьким и использовал for-each.

XSLT является декларативным , что означает, что вы описываете, что должно произойти, если встречаются определенные узлы, но вполне законно включать шаблоны, которые никогда не вызываются или вызываются неочевидными способами. Точно так же использование <xsl:apply-templates /> не дает представления о том, какие элементы находятся внутри известного элемента.

Например:

<xsl:template match="book">
    <xhtml:div class="book">
        <xsl:apply-templates />
    </xhtml:div>
</xsl:template>

<xsl:template match="title">
    <xhtml:h1><xsl:value-of select="."/></xhtml:h1>
</xsl:template>

<xsl:template match="chapter/title">
    <xhtml:h2><xsl:value-of select="."/></xhtml:h2>
</xsl:template>

Есть ли у книги название? У книг есть главы? У глав даже есть названия? Мы не знаем и не можем знать.

...