我在使用XSLT格式化XML文件时遇到了问题。通常我想要按顺序检索XML元素中包含的每个属性的值。
Currentlz它在XSLT中是硬编码的,我意识到如果我的XML文件发生变化,XSLT将无法完成它的工作。
我尝试使用<xsl:value-of select="@(name(@*[1]))" />
之类的东西来检索元素的第一个属性值,但它不起作用。
怎么做?
提前致谢。
目前的情况如下:
<xsl:for-each select="testsuites/testsuite/testcase">
<xsl:if test="@failure='PASSED'">
<tr style="color:green;font-weight:bold">
<td style="text-align:center">
<xsl:value-of select="@classname" />
</td>
<td style="text-align:center">
<xsl:value-of select="@name" />
</td>
<td style="text-align:center">
<xsl:value-of select="@Plate" />
</td>
<td style="text-align:center">
<xsl:value-of select="@Distance" />
</td>
<td style="text-align:center">
<xsl:value-of select="@Side" />
</td>
<td style="text-align:center">
<xsl:value-of select="@Angle" />
</td>
<td style="text-align:center">
<xsl:value-of select="@failure" />
</td>
<td style="text-align:center">
<xsl:value-of select="failure/@message" />
</td>
</tr>
</xsl:if>
... and so one
以下是我的XML文件的一部分:
<testsuites disabled="0" errors="0" failures="1" passes="16" skipped="0" tests="17" time="1">
<testsuite disabled="0" id="0" name="Bok" time="1" tests="4">
<testcase classname="XYZ" name="description" Plate="blah" Distance="A" Side="L" Angle="15" failure="PASSED">
<system-out/>
<system-err/>
</testcase>
<testcase classname="XYZ" name="description" Plate="blah" Distance="A" Side="L" Angle="60" failure="PASSED">
<system-out/>
<system-err/>
</testcase>
<testcase classname="XYZ" name="description" Plate="blah" Distance="A" Side="L" Angle="30" failure="PASSED">
<system-out/>
<system-err/>
</testcase>
<testcase classname="XYZ" name="description" Plate="blah" Distance="A" Side="L" Angle="60" failure="PASSED">
<system-out/>
<system-err/>
</testcase>
</testsuite>
... and so one
编辑:
好的,正如@TimC回答的那样,@(name(@*[1]))
我不需要括号和名字,对我来说没问题。
现在的问题是如何制作一个循环,它将迭代1中的元素,让我们说7,我的意思是这样的:
<xsl:for-each select="$var=1 to 7">
<td style="text-align:center">
<xsl:value-of select="@*[$var]" />
</td>
</xsl:for-each>
答案 0 :(得分:1)
我在使用XSLT格式化XML文件时遇到了问题。 通常我想要按顺序检索每个属性的值 包含在XML元素中。 Currentlz它在XSLT和I中是硬编码的 意识到如果我的XML文件发生变化,XSLT就无法完成它的工作。
输入XML的格式是否真的需要担心和解决?想一想。在任何情况下,现有转换是否能够在改变输入XML格式的情况下正确地完成其工作取决于转换的工作应该是什么,以及发生什么样的改变。
如果它的工作是以特定的顺序呈现一组特定的字段,那么我认为它将会令人钦佩地完成它的工作。特别是,它将以一致的顺序显示所选字段,而不管它们在输入文档中出现的顺序如何,为实际不存在的属性发出空单元格。如果输出是供人类消费的,那么所有这些都可能是好的事物。
我 试图用类似的东西 检索元素的第一个属性值,但它不起作用。
好的,正如@TimC回答的那样,我不需要@中的括号和名字(名称(@ * [1])) 对我来说没问题。
现在的问题是如何创建一个迭代元素的循环 从1开始,让我们说7
没有。如果你真的想这样做,那么就像程序员一样停止思考。 XSLT没有循环,本身。其操作模式涉及选择一个或多个节点,然后依次使用每个节点作为实例化模板的上下文。如果没有任何排序指令,它将按文档顺序处理节点。你试图让它变得比它需要的更难。
例如,如果要处理每个&lt; testcase&gt;的所有属性上下文节点,然后您需要的是这样的:
<xsl:for-each select="@*">
<td style="text-align:center">
<xsl:value-of select="." />
</td>
</xsl:for-each>
如果您只想处理前7个,无论有多少个,请在选择中指定:
<xsl:for-each select="@*[position() < 8]">
<td style="text-align:center">
<xsl:value-of select="." />
</td>
</xsl:for-each>
另一方面,如果您想确保准确发出7&lt; td&gt;每个测试用例的元素,无论是否有很多属性,然后你要回到原始XSL的某些行:
<td style="text-align:center">
<xsl:value-of select="@*[1]" />
</td>
<td style="text-align:center">
<xsl:value-of select="@*[2]" />
</td>
<!-- ... -->
否则你需要编写一个模板来执行迭代,可能是这样的:
<xsl:call-template name="iterate-testcase-attributes">
<xsl:with-param name="up-to" select="7"/>
</xsl:call-template>
...
<xsl:template name="iterate-testcase-attributes">
<xsl:param name="current" select="1"/>
<xsl:param name="up-to" select="1"/><!-- the select value is only a default -->
<td style="text-align:center">
<!-- will produce nothing if the context node has no such attribute -->
<xsl:value-of select="@*[position() = $current]" />
</td>
<xsl:if test="$current < $up-to">
<xsl:call-template name="iterate-testcase-attributes">
<xsl:with-param name="current" select="$current + 1"/>
<xsl:with-param name="up-to" select="$up-to"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
答案 1 :(得分:0)
正如评论中所提到的,XML中的属性是无序的。如果你想要获得所有属性而不管订单如何,你可以这样做......
testcase
但是,对于多个<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<table border="1">
<xsl:variable name="attrs" select="testsuites/testsuite[1]/testcase[1]/@*" />
<tr>
<xsl:for-each select="$attrs">
<th>
<xsl:value-of select="local-name()" />
</th>
</xsl:for-each>
</tr>
<xsl:for-each select="testsuites/testsuite/testcase[@failure='PASSED']">
<xsl:variable name="currentCase" select="." />
<tr style="color:green;font-weight:bold">
<xsl:for-each select="$attrs">
<xsl:variable name="currentAttr" select="local-name()" />
<td style="text-align:center">
<xsl:value-of select="$currentCase/@*[local-name() = $currentAttr]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
元素,无法保证每行中的属性具有相同的顺序。但是如果你真的想让你的XSLT尽可能通用,你可以将订单基于第一行。
试试这个XSLT
private boolean hasNetworkAccess() {
try {
HttpURLConnection urlc = (HttpURLConnection) (new URL("http://www.screens.company").openConnection());
urlc.setRequestProperty("User-Agent", "Test");
urlc.setRequestProperty("Connection", "close");
urlc.setConnectTimeout(3000);
urlc.connect();
return (urlc.getResponseCode() == 200);
} catch (IOException e) {
Log.e("NETWORK", "Error checking internet connection.");
}
return false;
}