我有一个样式表,它包含两个文件,一个来自工程库,另一个来自文档库,然后将它们合并以创建一些DITA文件(进一步处理)。最近,我试图将文档文件的内容分为通用文件和特定文件。因此,我的合并现在是一个包含两个文档文件的工程文件。
通用文件是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<messages xmlns:xs="http://www.w3.org/2001/XMLSchema">
<message id="IDENT_STRING">
....
</message>
</messages>
Run Code Online (Sandbox Code Playgroud)
特定文件具有指向通用文件的ENTITY标签:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE messages [
<!ENTITY generic-file SYSTEM "generic-file.xml">
]>
<messages> &generic-file; <!-- specific-file -->
<message id="IDENT_STRING2">
....
</message>
</messages>
Run Code Online (Sandbox Code Playgroud)
选择是这样写的:
<xsl:copy-of select="$docid/message[@id=$id]/doc/explanation/text()"/>
Run Code Online (Sandbox Code Playgroud)
这只会从特定文件中获取内容。直到我将select更改为两个斜杠后,我的样式表才能正常工作。这是正确的版本:
<xsl:copy-of select="$docid//message[@id=$id]/doc/explanation/text()"/>
Run Code Online (Sandbox Code Playgroud)
我对社区的问题是1)为什么第二种语法正确?和2)我将如何更快地找到它?
这是/ x / y // z是xpath的一个很好的信息来源,http://www.w3.org/TR/xpath/#location-paths
在缩写语法部分://是/ descendant-or-self :: node()/的缩写。例如,// para是/ descendant-or-self :: node()/ child :: para的缩写,因此将选择文档中的任何para元素(即使是文档元素的para元素也将由/选择/ para,因为文档元素节点是根节点的子节点);div // para是div / descendant-or-self :: node()/ child :: para的缩写,因此将选择div子级的所有para后代。
//是在xpath的开始还是中间,其含义是相同的。
就学习这些东西而言,对我来说,我必须构造小型的人工xml或我尝试转换的xml简化外壳,然后运行xslt。在Visual Studio中,可以追溯到2005年左右,这是一种相当方便的方法,我认为它仍然存在,尽管我有一段时间没有对此感到困惑。我发现MSDN或w3.org是很好的资源,尽管w3上的语言有时可能会被消化。
使用此xml:
<?xml version="1.0" encoding="utf-8"?>
<root>
<a id="a1">
<d id="1" />
<d id="2" />
</a>
<a id="a2">
<d id="3" />
<d id="4" />
</a>
<b>
<c id="1" />
<c id="2" />
</b>
</root>
Run Code Online (Sandbox Code Playgroud)
使用此xslt:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<test>
<xsl:apply-templates/>
</test>
</xsl:template>
<xsl:template match="b">
<z>
<select>//a</select>
<xsl:copy-of select="//a"/>
</z>
<z>
<select>.//a</select>
<xsl:copy-of select=".//a"/>
</z>
<z>
<select>.//c</select>
<xsl:copy-of select=".//c"/>
</z>
<z>
<select>/root/a/d</select>
<xsl:copy-of select="/root/a/d"/>
</z>
<z>
<select>/root/a</select>
<xsl:copy-of select="/root/a"/>
</z>
<z>
<question>so what is the node?</question>
<period>
<xsl:copy-of select="."/>
</period>
<slash>
<xsl:copy-of select="/"/>
</slash>
</z>
</xsl:template>
</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)
得到这个结果:
<?xml version="1.0" encoding="utf-8"?>
<test>
<z>
<select>//a</select>
<a id="a1">
<d id="1" />
<d id="2" />
</a>
<a id="a2">
<d id="3" />
<d id="4" />
</a>
</z>
<z>
<select>.//a</select>
</z>
<z>
<select>.//c</select>
<c id="1" />
<c id="2" />
</z>
<z>
<select>/root/a/d</select>
<d id="1" />
<d id="2" />
<d id="3" />
<d id="4" />
</z>
<z>
<select>/root/a</select>
<a id="a1">
<d id="1" />
<d id="2" />
</a>
<a id="a2">
<d id="3" />
<d id="4" />
</a>
</z>
<z>
<question>so what is the node?</question>
<period>
<b>
<c id="1" />
<c id="2" />
</b>
</period>
<slash>
<root>
<a id="a1">
<d id="1" />
<d id="2" />
</a>
<a id="a2">
<d id="3" />
<d id="4" />
</a>
<b>
<c id="1" />
<c id="2" />
</b>
</root>
</slash>
</z>
</test>
Run Code Online (Sandbox Code Playgroud)
因此,在构建xpath时,//将获得该节点类型的后代,如果从xpath开始使用//,则将转到文档。
如果您从开始。那么您将以当前节点开始xpath(如果使用xsl:apply-templates,则当前节点与xsl:template中的匹配后的节点相同,但如果使用xsl:call-template,则当前节点是相同的作为制作xsl:call-template的当前节点)。
如果您以/开头的xpath,那么您将引用文档的根目录。
假定$ docId是一个节点集,该节点集引用一个文档或另一个文档,它设置了xpath的起点,因此$ docId // message意味着获取节点集中的所有消息元素,即$ docId。
最后,您需要//的原因是您没有完全指定路径。在提供的示例中,我构造了一个/ root / a / d,它是d元素的完整路径,并将所有4个元素拉出。$ docId // message仅允许您查找位于$ docId节点集根目录之下的任何元素“ message”。有时您可能没有清晰的对称性来获取记录:例如,如果您具有/ messages / critical / message和/ messages / warning / message,则使用/ messages // message的xpath可能更方便//获得所需信息的消息。
我希望这有帮助。
归档时间: |
|
查看次数: |
3766 次 |
最近记录: |