【发布时间】:2014-09-28 19:30:43
【问题描述】:
我是 XML 和 XSLT 的新手,我想从 XML 文件中过滤一些信息。基于 XML 文件中某些标记值的匹配。当 XML 文件仅包含 1 或 2 个人标签信息时,我的解决方案有效。但是当使用具有更多个人信息的更大 xml 文件时。它失败了,只有最后一个人根据需要进行转换。
这是我的 XML 文件,如下所示:
<People>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<tag3>not important info</tag3>
<tag4>not important info</tag4>
<first-name>Mike</first-name>
<last-name>Hewitt</last-name>
<licenses>
<license>
<number>938387</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TX</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
<license>
<number>938387</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">IL</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
<appointments>
<appointment-info>
<code>5124</code>
<number>14920329324</number>
<licensed-states>
<state>TX</state>
</licensed-states>
</appointment-info>
</appointments>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<tag3>not important info</tag3>
<tag4>not important info</tag4>
<first-name>John</first-name>
<last-name>Jhonny</last-name>
<licenses>
<license>
<number>1762539</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TX</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
<license>
<number>1762539</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">NY</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
<appointments>
<appointment-info>
<code>5124</code>
<number>14920329324</number>
<licensed-states>
<state>TX</state>
</licensed-states>
</appointment-info>
</appointments>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<tag3>not important info</tag3>
<tag4>not important info</tag4>
<first-name>Danny</first-name>
<last-name>Hewitt</last-name>
<licenses>
<license>
<number>17294083</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">IL</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
<appointments>
<appointment-info>
<code>5124</code>
<number>14920329324</number>
<licensed-states>
<state>IL</state>
</licensed-states>
</appointment-info>
</appointments>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<tag3>not important info</tag3>
<tag4>not important info</tag4>
<first-name>Russel</first-name>
<last-name>Jhonny</last-name>
<licenses>
<license>
<number>840790</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">TX</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
<license>
<number>840790</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">NY</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
<license>
<number>840790</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">CA</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
<appointments>
<appointment-info>
<code>5124</code>
<number>14920329324</number>
<licensed-states>
<state>TX</state>
<state>NY</state>
</licensed-states>
</appointment-info>
</appointments>
</Person>
</People>
我想做的基本上是,如果一个人在某个州获得许可,例如德克萨斯州。并且在那个州有约会信息,例如 TX,从许可证中过滤掉。如果这是唯一的许可证信息,则过滤此人。
并且新的 xml 应该包含所需标签的信息。并且只有与预约许可证中的许可证不匹配的许可证才会说明并过滤匹配所有许可证的人。
这是我期望的输出:
<People>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>Mike</first-name>
<last-name>Hewitt</last-name>
<licenses>
<license>
<number>938387</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">IL</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>John</first-name>
<last-name>Jhonny</last-name>
<licenses>
<license>
<number>1762539</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">NY</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>John</first-name>
<last-name>Jhonny</last-name>
<licenses>
<license>
<number>840790</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">CA</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
</Person>
</People>
与该州的所有许可证匹配的第三人被过滤掉。目前我在示例中只使用了一种状态,但如果有多种状态,它应该能够过滤该信息。
如何编写 XSLT 来过滤此信息。我正在使用 XSLT 1.0 版
目前我能够应用此 XSLT 来获取转换所需的标签。但我不知道如何过滤许可证状态,它适用于较小的文件,但当我处理更大的文件时会失败。如果有人能指导我,我将不胜感激,因为我不明白出了什么问题,哪里出了问题。
这是我使用的 XSLT,如下所示:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!--Identity transform (aka identity template). This will match
and copy attributes and nodes (element, text, comment and
processing-instruction) without changing them. Unless a more
specific template matches, everything will get handled by this
template.-->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!--This template will match the "Person" element node. The "xsl:copy"
creates the new "Person" element. The "xsl:apply-templates" tells
the processor to apply templates to any attributes (of Person) or
elements listed in the "select". (Other elements will not be
processed.) I used the union operator in the "select" so I wouldn't
have to write multiple "xsl:apply-templates".-->
<xsl:template match="Person">
<xsl:copy>
<xsl:apply-templates select="@*|first-name|last-name|
required-tag1|required-tag2|licenses"/>
</xsl:copy>
</xsl:template>
<!--This template will match any "license" element nodes that have a child
"state" element whose value matches a "state" element node that is a
child of "licensed-states". Since the "xsl:template" is empty, nothing
is output or processed further.-->
<xsl:template match="license[state=//licensed-states/state]"/>
</xsl:stylesheet>
这就是我得到的输出,这是错误的。
<?xml version="1.0" encoding="UTF-8"?>
<People>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>Mike</first-name>
<last-name>Hewitt</last-name>
<licenses/>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>John</first-name>
<last-name>Jhonny</last-name>
<licenses/>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>Danny</first-name>
<last-name>Hewitt</last-name>
<licenses/>
</Person>
<Person>
<required-tag1>some-information</required-tag1>
<required-tag2>some-information</required-tag2>
<first-name>Russel</first-name>
<last-name>Jhonny</last-name>
<licenses>
<license>
<number>840790</number>
<state xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">CA</state>
<field xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Health</field>
</license>
</licenses>
</Person>
</People>
我只是不知道出了什么问题,因为当我从 xml 文件中删除最后两个人的信息并使用相同的 XSLT 对其进行测试时,它可以完美运行。而且我不知道如何删除匹配所有许可证的人的信息。
【问题讨论】:
-
@michael.hor257k 您好,先生,我是提出这个问题的人,我想我应该问一个新问题,因为在处理更大的 XML 文件时解决方案失败了。您能否指导我解决解决方案失败的原因?
-
你说的更大是什么意思?是否真的是文件的大小,或者是否包含导致 XSLT 失败的 small 文件中没有的其他特征。根据我的经验,XSLT 不太可能因大小而失败。您是否尝试逐步增加尺寸以找到“罪魁祸首”?
-
@MarcusRickert 感谢您的及时回复,我的意思是文件中的更多信息。上面的 xml 文件包含 4 个人信息,如果我使用 2 个人信息,xslt 工作完美。我已将此作为测试文件。但是我真的很想改造一个4000人的信息文件。
-
@MarcusRickert 我试图逐步增加文件信息,但它在工作信息上失败了。就像我只使用一个人信息作品,两个人信息作品,当我使用3个人信息时,第一人称转换是错误的,第二人称是预期的,第三人称是错误的,我无法找到罪魁祸首。