基于已知 XSL 对未知 XML 进行逆向工程
解决了!
在遵循 Matti 的建议后,我删除了自定义函数,一切都很好。
原始帖子:
从今天起我还是 XSLT 的新手,所以我确信这对你们中的许多人来说是理所当然的。无论如何:
我的任务是为我公司的网站创建一个小部件,该小部件使用第三方供应商提供的数据。
供应商拒绝向我们发送示例 XML 文件(甚至是只有元素标签的空白文件!),因此我尝试根据我在 XSLT 中看到的内容重新创建 XML他们确实派了我们。 (荒谬比比皆是)
这是我们发送的(已删除的)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() < $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" />&adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&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() < $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" />&adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&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 新手身份已经使这个项目花费了几个小时。
非常感谢任何帮助。
Solved!
After following Matti's suggestions, I removed the custom functions and all is well.
Original Post:
I'm new to XSLT as of today, so I'm sure this is a no-brainer for many of you. Anyways:
I've been tasked with creating a widget for my company's website that uses data provided by a 3rd-party vendor.
The vendor refuses to send us a sample XML file (even a blanked-out one with just the element tags!) so I'm trying to recreate the XML based on what I can see in the XSLT that they -did- send us. (ridiculosity abounds)
This is the (stripped) XSLT file we were sent:
<?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() < $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" />&adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&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() < $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" />&adid=<xsl:value-of select="paperitemid" /></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="href">http://website/?pid=<xsl:value-of select="$PaperId" />&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>
And my feeble attempt at reverse-engineering the 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>
There's no doubt in my mind that I'm overlooking something simple, but my novice status with XSLT has already made this a multi-hour project.
Any help is greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我的猜测更像是:
[]
内容并不是指元素名称的一部分,而是指元素的位置。所以元素名称就是Table
。descr
和paperid
元素。XSLT 似乎正在做的是将项目按列布置在列表中。是的,XSLT 就是这么复杂。
另外,如果定义了
imageurl
,它似乎会忽略paperid
和paperitemid
,如果定义了descr
,它似乎会忽略descr
提供了>shortdescr。这可能会对您的追求有所帮助。...顺便说一句,如果没有实际的 XML,您应该如何测试它?
My guess would be more like:
[]
stuff doesn't refer to parts of the element name, it refers to the position of the element. So the element name is justTable
.descr
andpaperid
elements.What the XSLT seems to be doing is laying out items on a list in columns. Yes, it is that ridiculously complicated in XSLT.
Also, it would seem that it's ignoring
paperid
andpaperitemid
ifimageurl
is defined, and ignoringdescr
ifshortdescr
is provided. This might help you on your quest....how are you supposed to test this without the actual XML, btw?
在一般情况下,不可能仅通过 XSLT 确定输入 XML 文件的结构
虽然在这种情况下,您可能能够基于 XSLT 对 XML 描述进行逆向工程,但在一般情况下情况下不可能正确执行。在本例中,这是可能的,因为模板很小并且使用了
for-each
。XSLT 是声明性的,这意味着您描述了遇到某些节点时应该发生的情况,但包含从未被调用或以不明显的方式调用的模板当然是合法的。类似地,使用
无法了解已知元素内有哪些元素。例如:
书有标题吗?书有章节吗?章节有标题吗? 我们不知道也不可能知道。
In the general case it is impossible to determine the structure of an input XML file given just an XSLT
While in this instance you may have been able to reverse engineer an XML descprion based on the XSLT, in the generic case its impossible to do correctly. In this instance it was possible because the template was small and used
for-each
.XSLT is declarative, which means you describe what should happen if certain nodes are encountered, but its certainly legal to include templates which are never called, or are called in ways that are not obvious. Similarly, the use of
<xsl:apply-templates />
gives no insight as to what elements are inside of a know element.For example:
Does book have a title? Do books have chapters? Do chapters even have titles? We don't and can't know.